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;
}

 

posted @ 2010-10-15 16:40  勇泽  阅读(344)  评论(0编辑  收藏  举报