题目链接:
K - Find them, Catch them
题目大意:警方决定捣毁两大犯罪团伙:龙帮和蛇帮,显然一个帮派至少有一人。该城有N个罪犯,编号从1至N(N<=100000。将有M(M<=100000)次操作。
D a b 表示a、b是不同帮派
A a b 询问a、b关系。
具体思路:带权并查集模板题。一般并查集都是相同的放在一个联通块里面。对于这个题,我们可以利用一下这个性质,只要是有联系的,都放进一个连通块里面,然后我们查询的时候,如果说他们的祖先一样的话,就首先能够保证是有关系的。然后就开始判断是敌对关系还是朋友关系。我们再加一个数组r[x],表示x和他的祖先的关系,如果r[x]=1代表和祖先是敌对关系,否则就是朋友关系。然后在寻找路径的过程中,不停地更新就可以了。
1 #include<iostream> 2 #include<stdio.h> 3 #include<map> 4 using namespace std; 5 # define ll long long 6 # define inf 0x3f3f3f3f 7 const int maxn = 2e5+100; 8 int father[maxn]; 9 int r[maxn]; 10 int Find(int t) 11 { 12 if(t==father[t]) 13 return t; 14 int tmp=father[t]; 15 father[t]=Find(father[t]); 16 r[t]=(r[tmp]+r[t])%2; 17 return father[t]; 18 } 19 void match(int t1,int t2) 20 { 21 int s1=Find(t1); 22 int s2=Find(t2); 23 father[s1]=s2; 24 r[s1]=(r[t1]+r[t2]+1)%2;//t1和t2是敌对关系 25 } 26 int main() 27 { 28 int T; 29 scanf("%d",&T); 30 while(T--) 31 { 32 int n,m; 33 scanf("%d %d",&n,&m); 34 for(int i=1; i<=n; i++) 35 { 36 father[i]=i; 37 r[i]=0; 38 } 39 char str[10]; 40 int st,ed; 41 while(m--) 42 { 43 scanf("%s",str); 44 if(str[0]=='A') 45 { 46 scanf("%d %d",&st,&ed); 47 if(Find(st)==Find(ed)) 48 { 49 if(r[st]==r[ed]) 50 { 51 printf("In the same gang. "); 52 } 53 else 54 printf("In different gangs. "); 55 } 56 else 57 { 58 printf("Not sure yet. "); 59 } 60 } 61 else 62 { 63 scanf("%d %d",&st,&ed); 64 match(st,ed); 65 } 66 } 67 return 0; 68 } 69 }