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

poj 1703(并查集)

时间:2015-05-01 20:00:37      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:并查集

题意:有n个人和两个阵营,给出两种操作,A a b ,询问a和b的是否在同一个阵营,如果有人未加入任何阵营输入不确定。D a b,让a和b成为不同阵营的。
题解:两种做法。
一种是把并查集扩大一倍,先给每个人一个假定的敌人,然后有D操作时把敌人加入到假定敌人的集合中,A操作判断a和b是否在同一个集合,如果不在判断对方是否在自己假定敌人的集合中,在就是敌人,否则是不确定。

#include <stdio.h>
#include <string.h>
const int N = 100005;
char str[5];
int n, m, pa[N];

int get_parent(int x) {
    return x == pa[x] ? x : pa[x] = get_parent(pa[x]);
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &n, &m);
        int nn = 2 * n;
        for (int i = 0; i <= nn; i++)
            pa[i] = i;
        while (m--) {
            int a, b;
            scanf("%s%d%d", str, &a, &b);
            int px = get_parent(a);
            int py = get_parent(b);
            if (str[0] == ‘A‘) {
                if (px == py)   
                    printf("In the same gang.\n");
                else {
                    int t1 = get_parent(a + n); 
                    int t2 = get_parent(b + n);
                    if (px == t2 || py == t1)
                        printf("In different gangs.\n");
                    else
                        printf("Not sure yet.\n");
                }
            }   
            else {
                int t1 = get_parent(a + n);
                int t2 = get_parent(b + n);
                if (px != py) {
                    pa[t2] = px;
                    pa[t1] = py;
                }
            }
        }
    }
    return 0;
}

另一种做法是带权并查集,用一个数组rel[i]表示人i和他集合中父亲结点的关系,1表示是同一个阵营,0表示不同阵营。每次找到a和b的祖先与和祖先的关系,然后如果是A操作,如果px==py祖先是同一个人,那么关系就可以确定,否则关系无法确定,如果是D操作,让py成为了px的父亲,就可以更新rel[px],枚举情况发现结果是a和px还有b和py的异或结果。

#include <stdio.h>
const int N = 100005;
char str[5];
int n, m, pa[N];
bool rel[N];

int get_parent(int x, bool &r) {
    r = true;   
    int temp = x;
    while (temp != pa[temp]) {
        if (rel[temp] == false)
            r = !r;
        temp = pa[temp];
    }
    pa[x] = temp;//压缩路径
    rel[x] = r;
    return temp;
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &n, &m);
        for (int i = 0; i <= n; i++) {
            rel[i] = true;
            pa[i] = i;
        }
        while (m--) {
            int a, b;
            scanf("%s%d%d", str, &a, &b);
            bool r1, r2;
            int px = get_parent(a, r1);
            int py = get_parent(b, r2);
            if (str[0] == ‘D‘) {
                pa[px] = py;
                rel[px] = r1 == r2 ? 0 : 1;//异或结果
            }
            else {
                if (px == py) {
                    if (r1 == r2)
                        printf("In the same gang.\n");
                    else
                        printf("In different gangs.\n");
                }
                else
                    printf("Not sure yet.\n");
            }
        }
    }
    return 0;
}

poj 1703(并查集)

标签:并查集

原文地址:http://blog.csdn.net/hyczms/article/details/45420317

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