码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 1703 - Find them, Catch them(加权并查集) 题解

时间:2017-09-14 16:55:59      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:父节点   input   void   ...   acm   get   题解   more   ++   

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。

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

题目大意:

N个人分属两个黑帮。给出M条信息。(M,N <= 10^5)

D x y表示已知x和y不在同一个黑帮中。

A x y表示询问x和y是否在一个黑帮中。如果是,输出In different gangs. 如果不是,输出In the same gang.如果未知,输出Not sure yet.

输入一个数字t表示数据组数(1 <= T <= 20),接下来每组数据中,第一行有两个数字n m,第二行至第m+1行按照上述格式给出信息。

输入保证所有数据没有冲突。

Sample Input

1
5 5
A 1 2
D 1 2
A 1 2
D 2 4
A 1 4

Sample Output

Not sure yet.
In different gangs.
In the same gang.

 

分析:参考博客

加权并查集主要是增加了一个数组(我称为jud数组)来判断当前节点与其根节点的关系。

jud值为0表示当前节点与根节点属于同一团伙,为1表示属于不同团伙。

剩下的不想解释了,自己看参考博客

每次find时,令jud[x] = (jud[x]+jud[fa[x]])%2。

这实际上是根据父节点与爷爷节点的关系和子节点与父节点的关系来判断子节点与爷爷节点的关系,递归得出当前节点与根节点的关系。

显然,如果jud[x] = jud[fa[x]] 子节点与爷爷节点就是同一团伙,jud = 0.而如果jud[x] != jud[fa[x]] 子节点与爷爷节点就是不同团伙,jud = 1.

每次merge时,更新两棵树的根节点的关系。找到a,b两点各自的根节点x,y,合并之后的jud[x] = (jud[a]+jud[b]+1)%2。

首先已知被合并的两个点a、b一定是不同团伙的(题目中D x y的意思就是说x与y不在同一团伙中)。

那么,如果a与x、b与y关系是相同的,则x与y就是不同团伙。否则是同一团伙。

表达无力...感觉还是我看的那篇博客叙述得更清楚,强烈推荐。

 

AC代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstring>
 5 
 6 const int MAXN = 100005;
 7 
 8 inline void read(int &x)
 9 {
10     char ch = getchar(),c = ch;x = 0;
11     while(ch < 0 || ch > 9) c = ch,ch = getchar();
12     while(ch >= 0 && ch <= 9) x = (x<<1)+(x<<3)+ch-0,ch = getchar();
13     if(c == -) x = -x;
14 }
15 
16 int n,m,t,x,y,fa[MAXN],jud[MAXN]; 
17 char op;
18 
19 int find(int x)
20 {
21     if(fa[x] == x)
22         return x;
23     int p = fa[x];
24     fa[x] = find(fa[x]);
25     jud[x] = (jud[x]+jud[p])%2;
26     return fa[x];
27 }
28 
29 void merge(int a,int b)
30 {
31     int x = find(a),y = find(b);
32 
33     fa[x] = y;
34     jud[x] = (jud[a]+jud[b]+1)%2;    
35 }
36 
37 inline void init()
38 {
39     for(int i = 0;i <= n;++ i)
40         fa[i] = i,jud[i] = 0;
41 }
42 
43 int main()
44 {
45     read(t);
46     while(t --)
47     {
48         read(n),read(m);
49         init();
50         for(int i = 1;i <= m;++ i)
51         {
52             op = getchar();
53             while(op < A) op = getchar();
54             read(x),read(y);
55             if(op == D)
56                 merge(x,y);    
57             else
58             {
59                 if(find(x) != find(y))
60                     printf("Not sure yet.\n");
61                 else
62                 {
63                     if(jud[x] == jud[y])
64                         printf("In the same gang.\n");
65                     else
66                         printf("In different gangs.\n");
67                 }
68             }
69         }
70     }
71     return 0;
72 }

 

POJ 1703 - Find them, Catch them(加权并查集) 题解

标签:父节点   input   void   ...   acm   get   题解   more   ++   

原文地址:http://www.cnblogs.com/shingen/p/7520684.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!