种类并查集的应用
定义并查集为:
并查集里的元素i-x表示i属于帮派x
同一个并查集的元素同时成立
定义并查集为:
并查集里的元素i-x表示i属于帮派x
同一个并查集的元素同时成立
可见所有元素个数为2 * N,如果i表示属于帮派A,那么i + N表示属于帮派B,
每次输入两个家伙不在同一帮派的时候,就合并他们分属两个帮派的元素。
每次输入两个家伙不在同一帮派的时候,就合并他们分属两个帮派的元素。
输入量比较大,要用scanf,用cin会超时
#include <cstdio>
#define N 100005
int f[2 * N];
int n, m;
void init()
{
for (int i = 1; i <= 2 * n; i++)
f[i] = i;
}
int find(int x)
{
return x == f[x] ? x : f[x] = find(f[x]);
}
void merge(int x, int y)
{
int t1 = find(x), t2 = find(y);
if (t1 != t2) f[t2] = t1;
}
int same(int x, int y)
{
return find(x) == find(y);
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int a, b, ans = 0;
char ch;
scanf("%d%d", &n, &m);
init();
while (m--)
{
getchar();
scanf("%c%d%d", &ch, &a, &b);
if (ch == 'D')//由于是两个集合是相对关系,所以每次维护两次。
{
merge(a, b + n);
merge(a + n, b);
}
else
{
if (same(a, b))//没有考虑same(a + n, b + n),是因为上边每次维护两次,
//关系是相对的,因此判断时只需要判断2种情况中的一种即可。
printf("In the same gang.\n");
else if (same(a, b + n))//下边没考虑same(a + n, b)也是同理
printf("In different gangs.\n");
else
printf("Not sure yet.\n");
}
}
}
return 0;
}