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

 

你可能感兴趣的:(catch)