Find them, Catch them---poj1703(并查集)

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

可以认为n个人和m句话;

每句话包含A a b;D a b;

刚开始关系不确定;

A a b 就是问ab 是否同类;

D a b就是告诉我们ab不同类;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <queue>
#include <algorithm>
using namespace std;

const int oo = 0x3f3f3f3f;
const int N = 100050;

int f[N], r[N];///r[i]代表f[i]与i的关系,1代表不同类,0代表同类;

int Find(int x)
{
    int k=f[x];
    if(x!=f[x])
    {
        f[x] = Find(f[x]);
        r[x] = (r[x]+r[k])%2;
    }
    return f[x];
}

int main()
{
    int t;
    scanf("%d", &t);

    while(t--)
    {
        char s[10];
        int n, m, i, a, b, fa, fb;

        scanf("%d%d", &n, &m);

        for(i=0; i<=n; i++)
        {
            f[i] = i;
            r[i] = 0;
        }

        for(i=1; i<=m; i++)
        {
            scanf("%s%d%d", s, &a, &b);

            if(s[0]==‘A‘)
            {

                fa = Find(a);
                fb = Find(b);

                if(fa!=fb)
                    printf("Not sure yet.\n");
                else
                {
                    if(r[a]==r[b])
                        printf("In the same gang.\n");
                    else
                        printf("In different gangs.\n");
                }

            }
            else
            {
                fa = Find(a);
                fb = Find(b);

                if(fa!=fb)
                {
                    f[fa] = fb;
                    r[fa] = (r[b] - r[a] + 1 + 2)%2;
                }
            }
        }
    }
    return 0;
}

时间: 2024-12-20 21:05:55

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

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

本题也是一道经典的并查集题目,只不过并不是直来直去的,因为需要维护两组关系:同一伙.不是同一伙. 那要怎么办呢,一开始我用了vector来保存对立面,建立两个并查集,结果很自然是超时的,因为循环了太多次. 之后看别人的题解,感觉有点复杂,看的不是很明白,只有一篇给出了一个简单的方法,然后我又重新看了食物链那道题,发现本题就是那道题的改编,可以使用相同的方法来维护多组关系. 就像食物链那道题一样,对每个人创建两个元素:i和i+n.用3*n个元素来建立并查集,这个并查集可以维护如下信息: 如果x和y

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并查集

直接搞. #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <set> #include &

poj1703Find them, Catch them(并查集以及路径压缩)

1 /* 2 题目大意:有两个不同的黑帮,开始的时候不清楚每个人是属于哪个的! 3 执行两个操作 4 A a, b回答a, b两个人是否在同一帮派,或者不确定 5 D a, b表示a, b两个人不在同一个帮派 6 7 思路:利用并查集将相同帮派的人合并到一起! 8 a ,b 不在同一个城市,那么 a, 和mark[b]就在同一个城市, 9 b 和 mark[a]就在同一个城市! 10 */ 11 #include<iostream> 12 #include<cstring> 13

[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

[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

poj 1703 Find them, Catch them 【并查集拓展】

Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 32514   Accepted: 10036 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 Drago

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的值进行不断的更新

POJ1703并查集(区分两个集合)

题意:输入n,m.n个人,m个规定/询问.一共有两个集合,A:询问a,b是否在同一个集合?D:表明a,b不在同一个集合.输出有三种,不在同一集合,在同一集合,不确定. 解析:其实有点离散化的意思.传统并查集是合并两个集合,而这个题是分开两个集合.那么可以这么做,想办法进行合并操作.输入a,b,a,b没有了关系,但是可以规定,a+n,b属同一集合,a,b+n属于同一集合.即,n右边a+n的那些和b放入同一集合,n右边b+n的那些和a放入同一集合,这样a,b就撇开了关系.就可以进行join()操作了

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

题目传送:Find them, Catch them 思路:用一个关系数组记录当前结点与其父亲的关系,0表示同类,1表示不同类 AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <v