並查集的經典題型,一共有兩種操作:兩個案件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;
}