输入D x y代表x于y不在一个团伙里
输入A x y要输出x与y是否在同一团伙或者不确定他们在同一个团伙里
解题思路:这道题真没做出来,参考了别人的思路,感觉别人的思路真实绝妙,最近期末,也没什么时间去想,去思考,真心可惜了,它的思路是除了表示并查集的数组p[x],还有个rank[x]表示rank中存放的是p[a]与a的关系,这样不同帮派的人也能放在同一棵树里边处理了,而且特别是那种只知道两个不属于同一方,却不知道具体哪一个是某一方的情况~~但要注意每次合并之后rank的改变,其次每次查找rank也需要改变,因为路劲改变了,父亲结点也改变了,rank需要更新。
附送两组数据:
1 4 4 D 1 2 D 3 4 D 1 4 A 1 3 ans : In the same gang. 1 2 1 A 1 2 ans : Not sure yet.
AC代码:(用scanf,cin要超时)
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<stdio.h>
using namespace std;
const int maxn=1e5+100;
int t,n,m,p[maxn],a,b,Rank[maxn];
char c;
void Make_Set(int n)
{
for(int i=1;i<=n;i++)
{
p[i]=i;
Rank[i]=1;
}
}
int Find_Set(int x)
{
if(x==p[x]) return x;
else
{
int tmp=p[x];
p[x]=Find_Set(p[x]);//不仅找到了根结点,还优化了路径
Rank[x]=(Rank[tmp]+Rank[x]+1)%2;
}
return p[x];
}
void Union_Set(int a,int b)
{
int tmp1=Find_Set(a);
int tmp2=Find_Set(b);
if(tmp1!=tmp2)
{
p[tmp1]=tmp2;
Rank[tmp1]=(Rank[a]+Rank[b])%2;//之前两个的父亲结点不同
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
Make_Set(n);
int cnt=0;
for(int i=0; i<m; i++)
{
getchar();
scanf("%c%d%d",&c,&a,&b);
if(c=='A')
{
if(Find_Set(a)==Find_Set(b))
{
if((Rank[a]+Rank[b])%2==0) printf("In the same gang.\n");
else printf("In different gangs.\n");
}
else printf("Not sure yet.\n");
}
else Union_Set(a,b);
}
}
return 0;
}