如题:http://poj.org/problem?id=1703
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 36346 | Accepted: 11153 |
Description
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
Output
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
思路:回顾了我之前做这题的代码,是根据如果2个人能确定关系,就并入一个集合,在根据rela数组来判断是否是一个帮派,这里换了一种方法,更好理解,对并查集很多问题都能很好的解决。
对于编号i的人,i代表i是A帮派,i+n代表i是B帮派,给出D a b时,就Union(a,b+n);Union(a+n,b)。给出查询时,if(same(a,b+n)||same(a+n,b)) ,则ab不同帮派,if(same(a,b)||same(a+n,b+n))则是相同帮派,否则不能确定。注意数据量很大,一定要用scanf、
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 100005
int f[N*2];
int rank[N*2];
int find(int x)
{
if(x==f[x])
return x;
return f[x]=find(f[x]);
}
void Union(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(rank[fx]>rank[fy])
{
f[fy]=fx;
}
else
{
f[fx]=fy;
if(rank[fx]==rank[fy])
rank[fy]++;
}
}
int same(int x,int y)
{
if(find(x)==find(y))
return 1;
return 0;
}
int main()
{
// freopen("C:\\1.txt","r",stdin);
int T;
cin>>T;
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
int i;
for(i=1;i<=n*2;i++)
{
f[i]=i;
rank[i]=0;
}
while(m--)
{
char str[5];
int a,b;
scanf("%s%d%d",str,&a,&b);
if(str[0]=='D')
{
Union(a,b+n);
Union(a+n,b);
}
else
{
if(same(a,b+n)||same(a+n,b))
cout<<"In different gangs."<<endl;
else if(same(a,b)||same(a+n,b+n))
cout<<"In the same gang."<<endl;
else
cout<<"Not sure yet."<<endl;
}
}
}
return 0;
}