Key Point:
相等关系:可传递的,使用并查集进行检验
不等关系:不可传递,使用set进行检验
(如 X1 != X2 X1 != X3 但是X2 = X3 是可以成立的)
数据分割 HDU - 6109
小w来到百度之星的赛场上,准备开始实现一个程序自动分析系统。
这个程序接受一些形如xi=xj 或 xi≠xj
的相等/不等约束条件作为输入,判定是否可以通过给每个 w 赋适当的值,来满足这些条件。
输入包含多组数据。
然而粗心的小w不幸地把每组数据之间的分隔符删掉了。
他只知道每组数据都是不可满足的,且若把每组数据的最后一个约束条件去掉,则该组数据是可满足的。
请帮助他恢复这些分隔符。
Input
第1行:一个数字L,表示后面输入的总行数。
之后L行,每行包含三个整数,i,j,e,描述一个相等/不等的约束条件,若e=1,则该约束条件为xi=xj ,若e=0,则该约束条件为 xi≠xj 。
i,j,L≤100000
xi,xj≤L
Output
输出共T+1行。
第一行一个整数T,表示数据组数。
接下来T行的第i行,一个整数,表示第i组数据中的约束条件个数。
Sample Input
6
2 2 1
2 2 1
1 1 1
3 1 1
1 3 1
1 3 0
Sample Output
1
6
思路:
检验关系式是否矛盾,如果出现矛盾,就是一组数据的结束。
这里使用并查集 表示相等关系,用set表示不等关系。
并查集的合并中 使用了启发式合并。(其实和之前并查集一样,用了num,将num小的加大到num大的上面,按秩合并,但是我这里没有用也过了23333)
-
需要注意的是:当x和y合并时,需要把x所在集合的代表元素fx的set 和 y所在集合的代表元素fy的set 合并,(而不是把x和y的set合并,因为我们在进行检验时,他们都到一个集合里了,那么不等关系也要共享,我们不可能把x的set给集合中的每一个元素都共享一遍,我们只需要把x的set给代表元素fx(即集合的根)即可,因为我们在check时,也使用的是代表元素fx,而不是x。)
-
将x和y合并时,如果把fy作为新的根,那么只需要把fx的set加给fy就可以了,不需要吧fy的也加给fx,因为fa[fx]要变成fy,即fx的代表元素也换成了fy了。
-
因此,Merge函数和Find函数都需要 加上set的部分。( Find 需要将儿子的set并给父节点。) (Merge就和上面说的一样。)
AC代码:
#include <iostream>
#include <set>
#include <iterator>
using namespace std;
const int maxn = 1e5 + 5;
int fa[maxn], ans[maxn];
int n;
set<int> s[maxn];
void Push(int x, int p)
{
set<int>::iterator it;
for(it = s[x].begin(); it != s[x].end(); it++)
s[p].insert(*it);
}
int Find(int x)
{
if(fa[x] == x)
return x;
Push(x, fa[x]);
return fa[x] = Find(fa[x]);
}
void Merge(int x, int y)
{
int fx = Find(x), fy = Find(y);
if(fx == fy)
return;
Push(fx, fy);
fa[x] = fy;
}
void Init()
{
for(int i = 0; i <= n; i++)
{
fa[i] = i;
s[i].clear();
}
}
int main()
{
scanf("%d", &n);
Init();
int u, v, e;
int cnt = 0, t = 0;
for(int i = 0; i < n; i++)
{
scanf("%d%d%d", &u, &v, &e);
cnt++;
int fx = Find(u);
int fy = Find(v);
if(e == 1)
{
if(s[fx].find(fy) == s[fx].end() && s[fy].find(fx) == s[fy].end())
{
Merge(fx, fy);
continue;
}
}
else
{
if(fx != fy)
{
s[fx].insert(fy);
s[fy].insert(fx);
continue;
}
}
ans[++t] = cnt;
cnt = 0;
Init();
}
printf("%d\n", t);
for(int i = 1; i <= t; i++)
printf("%d\n", ans[i]);
return 0;
}