Description
在这个城市里有两个黑帮团伙,现在给出n个人,每个人都属于这两个帮派中的一个,m次操作,操作分两种:
1.D x y:x于y不在一个团伙里
2.A x y:查询x与y的关系,即是否在同一团伙或者不确定
Input
第一行一个整数T表示用例组数,每组用例第一行为两个整数n和m分别表示人数和操作数,之后m行每行表示一种操作(1<=n<=100000)
Output
对于每次查询,如果两个人在一个团伙则输出”In the same gang.“,如果两个人不在一个团伙则输出”In different gangs.“,如果不确定则输出”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.
Solution
并查集,食物链弱化版,对每个人i建立两个元素i和i+n分别表示这个人属于团伙1和团伙2,则
1.两个人不属于同一团伙:unite(x,y+n),unite(x+n,y)
2.判断两人是否属于同一团伙:same(x,y)表示x和y属于同一团伙,same(x,y+n)表示x和y属于不同团伙,两者都不成立说明x和y关系不确定
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 211111
int par[maxn];
int deep[maxn];
void init(int n)
{
for(int i=0;i<=n;i++)
{
par[i]=i;
deep[i]=0;
}
}
int find(int x)
{
if(par[x]==x) return x;
else return par[x]=find(par[x]);
}
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y) return;
if(deep[x]<deep[y]) par[x]=y;
else
{
par[y]=x;
if(deep[x]==deep[y]) deep[x]++;
}
}
bool same(int x,int y)
{
return find(x)==find(y);
}
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
char op[3];
int x,y;
init(2*n);
while(m--)
{
scanf("%s%d%d",op,&x,&y);
if(op[0]=='A')
{
if(same(x,y))printf("In the same gang.\n");
else if(same(x,y+n))printf("In different gangs.\n");
else printf("Not sure yet.\n");
}
else unite(x,y+n),unite(x+n,y);
}
}
return 0;
}