POJ1703Find them, Catch them 【种类并查集】

题目链接:http://poj.org/problem?id=1703

题目大意:给n个人,m次询问。A代表询问a, b之间的关系,D代表给出a, b属于不同的帮派。

我的想法:

太菜了,上课的时候没想到这种方法。

思路:

1.感觉有点像2-sat的思想,对于D给出的a, b两人属于不同帮派。我们就将a于b的对立点用并查集维护在一个集合中,也将b于a的对立点连通。

2.查询时,若a,b两人pre值相等则属于同一帮派。若a与b的对立点属于同一集合,或b与a的对立点属于同一集合,则说明a与b属于不同帮派。若上述都不成立则说明关系还未知。

3.对立点是虚构的,不能影响到原来的点。所以数据范围翻倍,x + n代表x的对立点。

注意:不能用 cin 输入,会超时。只能用scanf

 1 #include<stdio.h>
 2 const int maxn = 2e5 + 1e4;
 3 
 4 int pre[maxn];
 5 
 6 int find(int x)
 7 {
 8     if(pre[x] == x)
 9         return x;
10     else
11     {
12         int root = find(pre[x]);
13         pre[x] = root;
14         return pre[x];
15     }
16 }
17 
18 int main()
19 {
20     int T;
21     scanf("%d", &T);
22     while(T --)
23     {
24         int n, m;
25         scanf("%d%d", &n, &m);
26         getchar();
27         for(int i = 1; i <= 2 * n; i ++)
28         {
29             pre[i] = i;
30         }
31         for(int i = 1; i <= m; i ++)
32         {
33             char ch;
34             int a, b;
35             scanf("%c%d%d", &ch, &a, &b);
36             if(ch == 'D')
37             {
38                 int x = find(a), y = find(b);
39                 int xx = find(a + n), yy = find(b + n);
40                 if(x != yy)
41                     pre[yy] = x;
42                 if(y != xx)
43                     pre[xx] = y;
44             }
45             if(ch == 'A')
46             {
47                 int x = find(a), y = find(b);
48                 int xx = find(a + n), yy = find(b + n);
49                 if(x == y)
50                     printf("In the same gang.
");
51                 else if(x == yy || y == xx)
52                     printf("In different gangs.
");
53                 else
54                     printf("Not sure yet.
");
55             }
56             getchar();
57         }
58     }
59     return 0;
60 }
POJ1703
原文地址:https://www.cnblogs.com/yuanweidao/p/10931777.html