题目链接:POJ-1703
并查集的变形应用
建立两个数组,a[ ]用来表示双亲结点,b[ ]来表示与x不同的帮派的编号,只需要一个就够了,应为一个通过 函数find可以找的他的parent。
part 1 建立找双亲的函数 findx()
int findx(int x)
{
if(x!=a[x])
{
a[x]=findx(a[x]);
}
return a[x];
}
注:如果x和a[x]相等那么x就是双亲直接返回,否则进行递归,一直到双亲,然后返回a[x]。
part 2 建立对新来结点的建树
void set1(int x,int y)
{
x=findx(x);
y=findx(y);
if(x==y)
return ;
a[x]=y;
}
注:通过建立的findx函数找到输入的x,y的双亲如果是一个结点直接返回,否则,将一个作为孩子连上。比如,上面代码中,将x的a[x]=y,x就变成了y的孩子。
part 3 最终代码
#include <iostream>
using namespace std;
#include <cstdio>
int a[100010];
int b[100010];
int findx(int x)
{
if(x!=a[x])
{
a[x]=findx(a[x]);
}
return a[x];
}
void set1(int x,int y)
{
x=findx(x);
y=findx(y);
if(x==y)
return ;
a[x]=y;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int n,m;
cin>>n>>m;
for(int i=1; i<=n; i++)
{
a[i]=i;
b[i]=0;
}
getchar(); //下一个要输入字符
while(m--)
{
char c;
int x,y;
scanf("%c %d %d",&c,&x,&y);
getchar(); //为下一次做准备。
if(c=='D')
{
if(b[x]==0&&b[y]==0)
{
b[x]=y; //注意点1
b[y]=x;
}
else if(b[x]==0)
{
b[x]=y;
set1(x,b[y]);
}
else if(b[y]==0)
{
b[y]=x;
set1(y,b[x]);
}
else
{
set1(x,b[y]);
set1(y,b[x]);
}
}
else if(c=='A')
{
if(findx(x)==findx(y))
cout<<"In the same gang."<<endl;
else if(findx(x)==findx(b[y]))
cout<<"In different gangs."<<endl;
else
cout<<"Not sure yet."<<endl;
}
}
}
return 0;
}
注意点1:a[x]=y;a[y]=x;
为什么呢?应为题目x,y是不同的帮派,互换以后,当下一个数据输入的时候,寻找双亲findx,a[y]就会走x的值,将新的赋值到x上,而不是y。*