Find them, Catch them POJ 1703(并查集)

原题

题目链接

题目分析

并查集经典用法,是维护信息的并查集.由于只有两个帮派,那对于每个人需要给它创建两条信息,属于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 }

猜你喜欢

转载自www.cnblogs.com/VBEL/p/11418123.html
今日推荐