Find them, Catch them --POJ 1703
1、题目类型:并查集。
2、解题思路:并查集的应用。题意,城市里面有两个黑帮团伙Gang Dragon和Gang Snake,一共有n名团伙成员(还不知道属于这两个黑帮的哪一个)。现在警察局有一些信息,每条信息包含2个人编号,表示这2个人属于不同的帮派。问给你2个人的编号,能否确定他们是否属于同一个帮派。思路,用father[x]表示其所在并查集的父节点,other[x]表示一个与x处于不同帮派的人的编号,只需要1个就够了,因为只需要这么1个编号就能找出它的集合代表,若y的集合代表与之相同,则x与y为不同帮派,rank[x]表示以x为父亲节点的并查集中节点数目。
3、注意事项:注意合并并查集时的更新操作;注意当n=2的情况;注意询问同一个人的情况。
4、实现方法:
#include<iostream>
using namespace std;
#define M 0
int father[M+5];//标示其父节点
int other[M+5];//标示其对手节点
int rank[M+5];//标示其并查集中数目
int Find(int x)
{
if (x != father[x])
{
father[x] = Find(father[x]);
}
return father[x];
}
void Union(int x, int y)
{
x = Find(x);
y = Find(y);
if (x == y) return;
if (rank[x] > rank[y])
{
father[y] = x;
}
else
{
if (rank[x] == rank[y])
{
rank[y]++;
}
father[x] = y;
}
}
int main()
{
int i,c,p,n,a,b;
char ch;
cin>>c;
while(c--)
{
memset(father,0,sizeof(father));
memset(other,0,sizeof(other));
memset(rank,0,sizeof(rank));
scanf("%d%d",&p,&n);
for(i=0;i<n;i++)
{
getchar();
scanf("%c %d %d",&ch,&a,&b);
switch(ch)
{
case 'A':
if(a==b)
{
cout<<"In the same gang."<<endl;
break;
}
if(p==2)
{
cout<<"In different gangs."<<endl;
break;
}
if(father[a] && father[b])
{
int a1=Find(a),b1=Find(b),p=Find(other[a]);
if(a1==b1)
cout<<"In the same gang."<<endl;
else
{
if(b1==p)
cout<<"In different gangs."<<endl;
else
cout<<"Not sure yet."<<endl;
}
}
else
cout<<"Not sure yet."<<endl;
break;
case 'D':
if(father[a] && father[b])
{
Union(b,other[a]);
Union(a,other[b]);
}
else
{
if( (!father[a]) && (!father[b]) )
{
father[a]=a;
father[b]=b;
other[a]=b;
other[b]=a;
}
else if( father[a] && (!father[b]) )
{
father[b]=b;
other[b]=a;
Union(other[a],b);
}
else
{
father[a]=a;
other[a]=b;
Union(other[b],a);
}
}
break;
};
}
}
return 0;
}