POJ1703--Find them, Catch them(种类并查集)

Time Limit: 1000MS
Memory Limit: 10000K

Total Submissions: 32909
Accepted: 10158

Description

The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon and Gang Snake. However, the police first needs to identify which gang a criminal belongs to. The present question is, given two criminals; do they belong to a same clan? You must give your judgment based on incomplete information. (Since the gangsters are always acting secretly.)
Assume N (N <= 10^5) criminals are currently in Tadu City, numbered from 1 to N. And of course, at least one of them belongs to Gang Dragon, and the same for Gang Snake. You will be given M (M <= 10^5) messages in sequence, which are in the following two kinds:
1. D [a] [b]
where [a] and [b] are the numbers of two criminals, and they belong to different gangs.
2. A [a] [b]
where [a] and [b] are the numbers of two criminals. This requires you to decide whether a and b belong to a same gang.

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case begins with a line with two integers N and M, followed by M lines each containing one message as described above.

Output

For each message "A [a] [b]" in each case, your program should give the judgment based on the information got before. The answers might be one of "In the same gang.", "In different gangs." and "Not sure yet."

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.

Source

POJ Monthly--2004.07.18

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

思路:

种类并查集的裸题,

注意写法,很巧妙,有效地处理了更改一个节点的rank值,就必须更改此节点所在集合中所有节点的值的问题

  1 /*
  2 * @FileName: D:\代码与算法\2017训练比赛\七月训练三\1005-pro.cpp
  3 * @Author: Pic
  4 * @Date:   2017-07-22 18:50:32
  5 * @Last Modified time: 2017-07-22 21:38:49
  6 */
  7  #include<cstdio>
  8
  9 const int N = 100005;
 10 int n, m, f[N], rank[N];
 11
 12 inline void init(){
 13     for(int i=1; i<=n; ++i)
 14         f[i]=i,rank[i]=0;
 15 }
 16
 17 int find(int x){
 18     if(x==f[x])return f[x];
 19     int fa=f[x];
 20     f[x] = find(f[x]);
 21     rank[x] = (rank[x]+rank[fa])&1; //这一步的作用是将Line29做的更改传递下去
 22     return f[x];
 23 }
 24
 25 inline bool Union(int x,int y){
 26     int a=find(x), b=find(y);
 27     if(a==b) return false;
 28     f[b] = a;
 29     rank[b] = (rank[x]-rank[y]+1)&1; //rank[b]初始一定是0(初始化),若rank[x]与rank[y]一开始是相同的,则需要更改rank[b],否则不需要
 30 }
 31
 32 int main(){
 33     int T,a,b,fa,fb;
 34     char ch;
 35     scanf("%d",&T);
 36     while(T--){
 37         scanf("%d%d%*c",&n,&m);
 38         init();
 39         for(int i=0; i<m; ++i){
 40             scanf("%c%d%d%*c",&ch,&a,&b);
 41             if(ch==‘D‘){
 42                 Union(a,b);
 43             }
 44             else{
 45                 fa = find(a), fb=find(b);
 46                 if(fa==fb){
 47                     if(rank[a]==rank[b]) puts("In the same gang.");
 48                     else puts("In different gangs.");
 49                 }
 50                 else
 51                     puts("Not sure yet.");
 52             }
 53         }
 54     }
 55     return 0;
 56 }
 57 //
 58 //                       _oo0oo_
 59 //                      o8888888o
 60 //                      88" . "88
 61 //                      (| -_- |)
 62 //                      0\  =  /0
 63 //                    ___/`---‘\___
 64 //                  .‘ \\|     |// ‘.
 65 //                 / \\|||  :  |||// \
 66 //                / _||||| -:- |||||- \
 67 //               |   | \\\  -  /// |   |
 68 //               | \_|  ‘‘\---/‘‘  |_/ |
 69 //               \  .-\__  ‘-‘  ___/-. /
 70 //             ___‘. .‘  /--.--\  `. .‘___
 71 //          ."" ‘<  `.___\_<|>_/___.‘ >‘ "".
 72 //         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
 73 //         \  \ `_.   \_ __\ /__ _/   .-` /  /
 74 //     =====`-.____`.___ \_____/___.-`___.-‘=====
 75 //                       `=---=‘
 76 //
 77 //
 78 //     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 79 //
 80 //               佛祖保佑         永无BUG
 81 //
 82 //
 83 //
时间: 2024-10-11 23:00:42

POJ1703--Find them, Catch them(种类并查集)的相关文章

[poj1703]Find them, Catch them(种类并查集)

题意:食物链的弱化版本 解题关键:种类并查集,注意向量的合成. $rank$为1代表与父亲对立,$rank$为0代表与父亲同类. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> using namespace std; typedef long long ll; #de

poj1703 Find them,Catch them 【并查集】

做过一些的带权并查集,再来做所谓的"种类并查集",发现好像就顿悟了. 种类并查集与带权并查集实质上的差别并不大, 关键的区别就是种类并查集只是带权并查集再弄个%取余操作而已,然后余数就表示他属于哪个种类. 这题只有两个种类,也就是只有0和1两种, 对于两个不同的种类,那么之间的权值是相差1的,所以按照带权并查集的方法做加上1,然后取余2即可. #include<cstdio> const int N = 100005; int n, m, f[N], rank[N]; in

[POJ1703]Find them, Catch them(并查集)

传送门 1.开两个并查集 f[x] 表示 x 的同类 f[x + n] 表示 x 的敌人 ——代码 1 #include <cstdio> 2 #include <iostream> 3 #define N 200001 4 5 int T, n, m; 6 int f[N]; 7 8 inline int read() 9 { 10 int x = 0, f = 1; 11 char ch = getchar(); 12 for(; !isdigit(ch); ch = getc

POJ - 1703 Find them, Catch them(种类并查集)

题意:N个人,M条关系,A x y表示询问x和y是不是属于同一组,D x y表示x和y是不同组.输出每个询问后的结果. 分析: 1.所有的关系形成一个连通图,如果x和y可达,那两者关系是确定的,否则不能确定. 2.r[tmpy] = r[x] + r[y] + 1;可以更新连通块里祖先的标号. eg: 5 4 D 1 2 D 2 3 D 4 5-----到此为止形成两个连通块,标号如图所示(红笔) D 3 5 第四步,将3和5连边,因为以0为祖先,所以4的标号应当改变,可以发现改变后的r[4]

poj 2492 a bug&#39;s life 简单种类并查集

题意大致为找同性恋的虫子.... 这个比食物链要简单些.思路完全一致,利用取余操作实现关系之间的递推. 个人感觉利用向量,模和投影可能可以实现具有更加复杂关系的并查集. 1 #include<cstdio> 2 using namespace std; 3 const int MAXN=50010; 4 int fa[MAXN]; 5 int rel[MAXN]; // 0代表同类,1代表吃fa[i],2代表被吃 6 void _set(int n) 7 { 8 for(int i=1;i&l

POJ1182 食物链---(经典种类并查集)

题目链接:http://poj.org/problem?id=1182 食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 69207   Accepted: 20462 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食

poj1733(种类并查集+离散化)

题目链接: http://poj.org/problem?id=1733 题意: 输入n表示有一个长度为n的0,1字符串, m表示接下来有m行输入, 接下来的m行输入中x, y, even表示第x到第y个字符中间1的个数为偶数个, x, y, odd表示第x到第y个字符中间1的个数为奇数个, 若m句话中第k+1是第一次与前面的话矛盾, 输出k; 思路: 若x, y之间1的个数为偶数个, 那么1~x 与1~y中1的个数同奇偶性, 反之则异奇偶性, 我们可以将其理解为若输入x, y, even, 即

poj 1182 食物链(种类并查集 ‘初心者’)

题目链接:http://poj.org/problem?id=1182 借着这题可以好好理解一下种类并查集,这题比较简单但挺经典的. 题意就不解释了,中问题. 关于种类并查集结局方法也是挺多的 1扩增倍数. 就是有几种关系就建立几倍数组,具体方法在这里不详细说了,这种方法有弊端 比较复杂而且内存消耗比较大如果关系比较多就容易爆掉. 2向量的方法. 这种方法要详细解说一下.这个方法好处都有啥.......(自行脑补后面的话) 这个方法的优点占用内存比较小而且比较简洁.只要找到关系就行. 下面就用方

poj1417(种类并查集+dp)

题目:http://poj.org/problem?id=1417 题意:输入三个数m, p, q 分别表示接下来的输入行数,天使数目,恶魔数目: 接下来m行输入形如x, y, ch,ch为yes表示x说y是天使,ch为no表示x说y不是天使(x, y为天使,恶魔的编号,1<=x,y<=p+q):天使只说真话,恶魔只说假话: 如果不能确定所有天使的编号,输出no,若能确定,输出所有天使的编号,并且以end结尾: 注意:可能会有连续两行一样的输入:还有,若x==y,x为天使: 思路:种类并查集+