poj1703 Find them, Catch them(带权并查集)

题目链接

http://poj.org/problem?id=1703

题意

有两个帮派:龙帮和蛇帮,两个帮派共有n个人(编号1~n),输入m组数据,每组数据为D [a][b]或A [a][b],D[a][b]表示a,b属于不同的帮派,A [a][b]则让我们判断a,b是否属于一个帮派,根据判断的结果进行相应的输出。

思路

这题和poj2492很像,使用并查集解决,方法我已在poj2492的题解中写出,这里不再赘述。

代码

 1 #include <cstdio>
 2 using namespace std;
 3
 4 const int N = 100000 + 10;
 5 int p[N];
 6 int r[N];
 7
 8 void make_set(int n)
 9 {
10     for (int i = 1;i <= n;i++)
11     {
12         p[i] = -1;
13         r[i] = 0;
14     }
15 }
16
17 int find_root(int x)
18 {
19     if (p[x] == -1)
20         return x;
21
22     int t = p[x];
23     p[x] = find_root(p[x]);
24     r[x] = (r[x] + r[t]) % 2;
25     return p[x];
26 }
27
28 void union_set(int a, int b)
29 {
30     int ra = find_root(a);
31     int rb = find_root(b);
32
33     if (ra != rb)
34     {
35         p[ra] = rb;
36         r[ra] = (r[a] + r[b] + 1) % 2;
37     }
38 }
39
40 int main()
41 {
42     //freopen("poj1703.txt", "r", stdin);
43     int t;
44     scanf("%d", &t);
45     while (t--)
46     {
47         int n, m;
48         scanf("%d%d", &n, &m);
49         make_set(n);
50         char c;
51         int a, b;
52         for (int i = 0;i < m;i++)
53         {
54             getchar();
55             scanf("%c%d%d", &c, &a, &b);
56             if (c == ‘A‘)
57             {
58                 if (find_root(a) == find_root(b))    //a,b在一个集合里
59                 {
60                     if (r[a] == r[b])    //a,b为同一帮派
61                         puts("In the same gang.");
62                     else puts("In different gangs.");    //a,b为不同帮派
63                 }
64                 else puts("Not sure yet.");    //a,b不再同一集合里,故不确定
65             }
66             else union_set(a, b);
67         }
68     }
69     return 0;
70 }

注意点

1、函数union_set要写成这样:

//正确写法
void union_set(int a, int b)
{
    int ra = find_root(a);
    int rb = find_root(b);

    if (ra != rb)
    {
        p[ra] = rb;
        r[ra] = (r[a] + r[b] + 1) % 2;
    }
}

写成如下形式会MLE:

//错误写法,MLE
void union_set(int a, int b)
{
    int ra = find_root(a);
    int rb = find_root(b);

    p[ra] = rb;
    r[ra] = (r[a] + r[b] + 1) % 2;
}

2、使用scanf输入。

相似题目

1、poj2492

时间: 2024-12-28 00:34:33

poj1703 Find them, Catch them(带权并查集)的相关文章

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

传送门 Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 42463   Accepted: 13065 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 D

(中等) POJ 1703 Find them, Catch them,带权并查集。

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

并查集练习2(带权并查集)

明天旅游去爬山逛庙玩,今天练一天然后早早睡觉啦~ poj1703 Find them, Catch them (带权并查集) 1 #include<cstdio> 2 const int N=1e5+1; 3 int f[N]; 4 int r[N];//表示与父节点的关系,0同类,1不同类 5 int n; 6 void init(){ 7 for(int i=1;i<=n;++i){ 8 f[i]=i; r[i]=0; 9 } 10 } 11 int fin(int x){ 12 i

poj2492 A Bug&#39;s Life【带权并查集】

题目链接:http://poj.org/problem?id=2492 题目描述:找基佬游戏(汗-_-b)有个hentai科学家研究虫子种群,不断地给出二元组xy,表示x和y是异性交往,但是可能会出现矛盾(找到基佬),比如1与2是异性恋,2与3是异性恋,却又告诉你1和3是异性恋.问种群中存不存在基佬败类 思路:与poj1182“食物链”几乎一样,还简单一点,毕竟只有两类物品.par[i]表示父节点,d[i]表示偏移量,0为同性,1为异性.不过要注意的一点是所有合并的过程要对二取模,比如x找到根结

hdu3038(带权并查集)

题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=3038 题意: n表示有一个长度为n的数组, 接下来有m行形如x, y, d的输入, 表示从第x,个元素到第y个元素的和为d(包括x, 和y), 问m行输入里面有几个是错误的(第一个输入是正确的); 思路: 很显然带权并查集咯,我们可以用距离的概念代替和的概念比较好理解一点,d表示x到y的和即x到y的距离; 可以用rank[x]表示x到其父亲节点的距离,  将正确的距离关系合并到并查集中

【POJ1182】 食物链 (带权并查集)

Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类. 第二种说法是"2 X Y",表示X吃Y. 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的.当一句话满足下列三条之

【poj 1988】Cube Stacking(图论--带权并查集 模版题)

题意:有N个方块,M个操作{“C x”:查询方块x上的方块数:“M x y”:移动方块x所在的整个方块堆到方块y所在的整个方块堆之上}.输出相应的答案. 解法:带权并查集.每堆方块作为一个集合,维护3个数组:fa[x]表示x方块所在堆的最顶部的方块:d[x]表示x方块所在堆的最底部的方块:f[x]表示x方块方块x上的方块数. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<

Lightoj1009 Back to Underworld(带权并查集)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Back to Underworld Time Limit:4000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Description The Vampires and Lykans are fighting each other to death. The war has become so fierc

[NOIP摸你赛]Hzwer的陨石(带权并查集)

题目描述: 经过不懈的努力,Hzwer召唤了很多陨石.已知Hzwer的地图上共有n个区域,且一开始的时候第i个陨石掉在了第i个区域.有电力喷射背包的ndsf很自豪,他认为搬陨石很容易,所以他将一些区域的陨石全搬到了另外一些区域. 在ndsf愉快的搬运过程中,Hzwer想知道一些陨石的信息.对于Hzwer询问的每个陨石i,你必须告诉他,在当前这个时候,i号陨石在所在区域x.x区域共有的陨石数y.以及i号陨石被搬运的次数z. 输入描述: 输入的第一行是一个正整数T.表示有多少组输入数据. 接下来共有

hdu 1558 Segment set【基础带权并查集+计算几何】

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3599    Accepted Submission(s): 1346 Problem Description A segment and all segments which are connected with it compose a segment set