并查集的经典题型,一共有两种操作:两个案件AB不是同一个团伙,询问AB是不是同一个团伙作案
我在结构体中定义两个元素,一个记录其父节下标,另一个记录其与父节点的关系,如果是同一个组织那么就记为0,否则记为1,在进行带路径压缩的查找父节点操作的时候可以用异或运算来计算节点与根节点的关系。
利用这种思路也可以解决另一道叫做“食物链”的题目
#include <memory.h>
#include <iostream>
#include <cstdio>
using namespace std;
#define maxn 100050
struct node{
int fa;
int relation;
};
node c[maxn]={0};
int findfa(int arg){
if(arg == c[arg].fa)
return arg;
int temp = c[arg].fa;
c[arg].fa = findfa(temp);
c[arg].relation ^= c[temp].relation;
return c[arg].fa;
}
void add(int arg1,int arg2){
int fa1 = findfa(arg1);
int fa2 = findfa(arg2);
c[fa2].fa = fa1;
c[fa2].relation =!(c[arg1].relation^c[arg2].relation);
}
void ask(int arg1,int arg2){
int fa1 = findfa(arg1);
int fa2 = findfa(arg2);
if(fa1 != fa2){
printf("Not sure yet.\n");
return;
}
if(c[arg1].relation == c[arg2].relation){
printf("In the same gang.\n");
}
else{
printf("In different gangs.\n");
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int m,n;
scanf("%d%d",&n,&m);
cin.get();
memset(c,0,sizeof(c));
for(int i=1;i<=n;++i)
c[i].fa = i;
while(m--){
char ins,h;
int arg1,arg2;
scanf("%c%d%d%c",&ins,&arg1,&arg2,&h);
switch(ins){
case 'D':
add(arg1,arg2);
break;
case 'A':
ask(arg1,arg2);
break;
default:
//printf("Input error!\n");
break;
}
/*for(int i=1;i<=n;++i)
printf("%d %d\n",c[i].fa,c[i].relation);*/
}
}
//system("pause");
return 0;
}