原题
题目分析
并查集经典用法,是维护信息的并查集.由于只有两个帮派,那对于每个人需要给它创建两条信息,属于1帮派和属于2帮派.这两条信息是相互矛盾的.当得到一条信息,a和b不是同伙的时候,只需要合并a是1帮派的信息和b是2帮派的信息以及a是2帮派的信息和b是1帮派的信息即可.这道题保证信息不会矛盾,因此只需要合并就行了,最后问a和b是不是同伙,只需要查询a是1帮派的信息和b是1帮派的信息是否在一起或a是2帮派的信息和b是2帮派的信息是否在一起就行了.
代码
1 #include <iostream> 2 #include <algorithm> 3 #include <utility> 4 #include <cstdio> 5 #include <cmath> 6 #include <cstring> 7 #include <string> 8 #include <vector> 9 #include <stack> 10 #include <queue> 11 #include <map> 12 #include <set> 13 14 using namespace std; 15 typedef long long LL; 16 const int INF_INT=0x3f3f3f3f; 17 const LL INF_LL=0x3f3f3f3f3f3f3f3f; 18 19 int crime[200000]; 20 int tree[200000]; 21 22 int ask(int x) 23 { 24 if(crime[x]==x) return x; 25 return crime[x]=ask(crime[x]); 26 } 27 28 void unite(int x,int y) 29 { 30 x=ask(x),y=ask(y); 31 if(x==y) return; 32 if(tree[x]<tree[y]) crime[x]=y; 33 else 34 { 35 crime[y]=x; 36 if(tree[x]==tree[y]) tree[x]++; 37 } 38 } 39 40 int main() 41 { 42 // freopen("black.in","r",stdin); 43 // freopen("black.out","w",stdout); 44 int t; 45 cin>>t; 46 while(t--) 47 { 48 int n,m; 49 cin>>n>>m; 50 getchar(); 51 for(int i=0;i<n;i++) crime[2*i]=2*i,crime[2*i+1]=2*i+1,tree[2*i]=0,tree[2*i+1]=0; 52 for(int i=0;i<m;i++) 53 { 54 char x; 55 int y,z; 56 scanf("%c %d %d",&x,&y,&z); 57 y--,z--; 58 if(x=='D') unite(2*y,2*z+1),unite(2*y+1,2*z); 59 else 60 { 61 if(ask(2*y)==ask(2*z)||ask(2*y+1)==ask(2*z+1)) printf("In the same gang.\n"); 62 else if(ask(2*y)==ask(2*z+1)||ask(2*y+1)==ask(2*z)) printf("In different gangs.\n"); 63 else printf("Not sure yet.\n"); 64 } 65 getchar(); 66 } 67 } 68 return 0; 69 }