POJ_1703 Find them, Catch them 【并查集】

一、题面

POJ1703

二、分析

需要将并查集与矢量法则相结合。par数组用以记录父节点,rank用以记录与父节点的关系。如题意,有两种关系,设定0是属于同一个帮派,1表示不属于同一个帮派。

运用并查集的时候判断x,y时考虑几种情况:

1.x与y父节点不相同:此时为不清楚两者关系。

2.x与y父节点相同,rank的值也相同:两者属于同一帮派。

3.x与y父节点相同,rank的值不相同:两者不属于同一帮派。

要得到这个关系,需要在并查集的find函数内对各个点的rank和par的值进行不断的更新。

对于rank,需要使用矢量加法,如

$\overrightarrow{AB}+\overrightarrow {BC}=\overrightarrow {AC}$

结合题目就是例:x的父节点px,如果x与父节点的关系是rank[x],px与父节点的关系是rank[px],那么x与par[px]的关系就是

$(rank[x] + rank[px])\%2$

其他的推理类似。

在find的路径压缩时,注意把rank关系进行更新即可,在union时涉及到x,y与它们的父节点px,py的rank值更新,其实原理相同。

三、AC代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <fstream>
 4 
 5 using namespace std;
 6 
 7 const int MAXN = 1e5+4;
 8 int par[MAXN];
 9 int Rank[MAXN];
10 
11 void init()
12 {
13     for(int i = 0; i < MAXN; i++)
14     {
15         par[i] = i;
16         Rank[i] = 0;
17     }
18 }
19 
20 int find(int x)
21 {
22     if(par[x] == x)
23         return x;
24     int px = par[x];
25     par[x] = find(par[x]);
26     Rank[x] = (Rank[px]+Rank[x])%2;
27     return par[x];
28 }
29 
30 void Union(int x, int y)
31 {
32     int px = find(x);
33     int py = find(y);
34     if(px == py)
35         return;
36     par[px] = py;
37     Rank[px] = (Rank[x]+1+Rank[y])%2;
38 }
39 
40 int main()
41 {
42     //freopen("input.txt", "r", stdin);
43     //freopen("out.txt", "w", stdout);
44     int T, M, N, x, y;
45     char op;
46     
47     while(scanf("%d", &T)!=EOF)
48     {
49         
50         while(T--)
51         {
52             init();
53             scanf("%d %d", &N, &M);
54             for(int i = 0; i < M; i++)
55             {
56                 getchar();
57                 scanf("%c %d %d", &op, &x, &y);
58                 if(op == 'A')
59                 {
60                     int px = find(x);
61                     int py = find(y);
62                     if(px != py)
63                     {
64                         puts("Not sure yet.");
65                     }
66                     else
67                     {
68                         if(Rank[x] == Rank[y])
69                             puts("In the same gang.");
70                         else
71                             puts("In different gangs.");
72                     }
73                 }
74                 else
75                 {
76                     Union(x, y);
77                 }
78             }
79         }
80     }
81     return 0;
82 }
View Code

猜你喜欢

转载自www.cnblogs.com/dybala21/p/10134417.html