题目大意:在这个城市里有两个黑帮团伙,现在给出N个人,问任意两个人他们是否在同一个团伙
输入D x y代表x于y不在一个团伙里
输入D x y代表x于y不在一个团伙里
输入A x y要输出x与y是否在同一团伙或者不确定他们在同一个团伙里
解题思路:这道题是一道很经典的种类并查集,除了有father[i]表示父亲节点外,还有rank[i]表示节点i与其父亲节点之间的关系,0表示是同类,1表示不同类。在路径压缩的时候要注意更新rank数组,这里的更新方法是向量偏移。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 100005;
int n,m,Fa[maxn],Rank[maxn]; //Rank[i]=1表示与祖先是不同的类,0表示相同类
int find(int x)
{
if(Fa[x] == x) return x;
int tmp = Fa[x];
Fa[x] = find(Fa[x]);
Rank[x] = (Rank[x] + Rank[tmp]) % 2;
return Fa[x];
}
int main()
{
int t,a,b,x,y;
char str[2];
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) Fa[i] = i, Rank[i] = 0;
for(int i = 1; i <= m; i++)
{
scanf("%s",str);
scanf("%d%d",&a,&b);
x = find(a);
y = find(b);
if(str[0] == 'A')
{
if(x != y)
printf("Not sure yet.\n");
else
{
if(Rank[a] == Rank[b])
printf("In the same gang.\n");
else printf("In different gangs.\n");
}
}
else
{
if(x == y) continue;
Fa[y] = x;
Rank[y] = (Rank[a] - Rank[b] + 1 + 2) % 2;
}
}
}
return 0;
}