http://poj.org/problem?id=1703
题目大意:
有一些罪犯,分两伙 每伙至少一个
两种操作
D a b:a和b不是一伙的
A a b:a和b 之间的关系是什么
思路:
并查集,先把可以确定关系的罪犯放在一个集里 再多一个数组
表示此节点和他指向的上一个节点是否一样(是否同伙)
代码及其注释:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<algorithm>
#include<set>
using namespace std;
const int N=100010;
int f[N];//他指向的上一个节点
int same[N];//和他指向的上一个节点是否同伙 1表示同伙 0表示不同伙
int findf(int x)
{
if(f[x]!=x)
{
int temp=f[x];//暂存
f[x]=findf(f[x]);
if(same[x]==same[temp])//更新所指向节点后 关系也要更新
{
same[x]=1;
}else
{
same[x]=0;
}
}
return f[x];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i)
{
f[i]=i;
same[i]=1;
}
while(m--)
{
char c;
int x,y;
getchar();
scanf("%c %d %d",&c,&x,&y);
if(c=='D')
{
int xf=findf(x);
int yf=findf(y);
f[xf]=yf;
if(same[x]==same[y])
{
same[xf]=0;
}else
{
same[xf]=1;
}
}else
{
if(n==2)//注意只有2个人的情况
{
printf("In different gangs.\n");
continue;
}
if(findf(x)!=findf(y))//是否可以确定关系 而且经过findf()函数 此点已经指向根节点
{
printf("Not sure yet.\n");
}else if(same[x]==same[y])//和根节点的关系是否一样
{
printf("In the same gang.\n");
}else
{
printf("In different gangs.\n");
}
}
}
}
return 0;
}