您的位置:首页 > 其它

pku 1703 Find them, Catch them

2010-07-26 17:20 176 查看
Find them, Catch them


Time Limit:
1000MS
Memory Limit:
10000K
Total
Submissions:

12875
Accepted:

3750
Description
The police office in Tadu City decides to say
ends to the chaos, as launch actions to root up the TWO gangs in the
city, Gang Dragon and Gang Snake. However, the police first needs to
identify which gang a criminal belongs to. The present question is,
given two criminals; do they belong to a same clan? You must give your
judgment based on incomplete information. (Since the gangsters are
always acting secretly.)

Assume N (N <= 10^5) criminals are currently in Tadu City,
numbered from 1 to N. And of course, at least one of them belongs to
Gang Dragon, and the same for Gang Snake. You will be given M (M <=
10^5) messages in sequence, which are in the following two kinds:

1. D [a] [b]

where [a] and [b] are the numbers of two criminals, and they belong
to different gangs.

2. A [a] [b]

where [a] and [b] are the numbers of two criminals. This requires
you to decide whether a and b belong to a same gang.

Input
The
first line of the input contains a single integer T (1 <= T <=
20), the number of test cases. Then T cases follow. Each test case
begins with a line with two integers N and M, followed by M lines each
containing one message as described above.
Output
For each message "A [a] [b]" in each case,
your program should give the judgment based on the information got
before. The answers might be one of "In the same gang.", "In different
gangs." and "Not sure yet."
Sample Input
1

5 5

A 1 2

D 1 2

A 1 2

D 2 4

A 1 4

Sample Output
Not sure yet.

In different gangs.

In the same gang.

Source
POJ
Monthly--2004.07.18

在wa了15次之后终于对了,不愧是学习并查集的经典题目(其实我在心里已经骂死这道题了),学到了很多东西。

并查集的高级应用,此题的思路是,当给出两个不再同一团伙的成员时将其与对方各自的敌人联合在一起。(这不是伟大领袖毛主席说过的:敌人的敌人是朋友!呵呵~)用一个数组op[]来记录敌人。起初在D操作中改了无数次,有重复判断的,有把敌人归到同一个团伙中的,改了7,8遍之后,觉得我的Union函数肯定没问题了,但依然坚定的wa!!!再错到14遍的时候我确定我的D操作时没有问题的,但从来没有检查过A操作,对比了一个AC的程序,将它的A操作改到我的A操作,结果也AC了……

通过分析改正了A的操作,终于AC;

结论:错的地方不一定是难的地方,往往真正要命的地方就是你觉得简单的地方,15wa谨记!

代码如下:

]#include <iostream>
using namespace std;
int p[100011];
int rank[100011];
int op[100013];
void make_set(int x)
{
p[x]=x;
rank[x]=0;
op[x]=x;
}
int find_set(int x)
{
if(x!=p[x])
p[x]=find_set(p[x]);
return p[x];
}
void Union(int x,int y)
{
y=find_set(y);
x=find_set(x);
if(x==y)
return;
if(rank[x]>rank[y])
{
p[y]=x;
}
else
{
p[x]=y;
if(rank[x]==rank[y])
rank[y]++;
}
}
int main()
{
int t;
scanf("%d",&t);
int m,n;
int i,j;
int x,y;
char action;
while(t--)
{

scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
make_set(i);
}
for(i=0;i<m;i++)
{
getchar();
scanf("%c%d%d",&action,&x,&y);
if(action=='A')
{
if(find_set(x)==find_set(y))
printf("In the same gang./n");
else
{
if((op[x]!=x&&find_set(op[x])==find_set(y))||(op[y]!=y&&find_set(op[y])==find_set(x)))
printf("In different gangs./n");
else
printf("Not sure yet./n");
}
}
else
{

if(op[y]!=y)
{//printf("Union(%d,%d):/n",find_set(x),find_set(op[y]));
Union(x,op[y]);}
if(op[x]!=x)
{//printf("Union(%d,%d):/n",find_set(y),find_set(op[x]));
Union(y,op[x]);}
op[x]=y;

op[y]=x;
//printf("x:%d  op[x]:%d    p[x]:%d/n",x,op[x],p[x]);
//printf("y:%d  op[y]:%d    p[y]:%d/n",y,op[y],p[y]);

}
}
}
//system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: