带权并查集--uva12232 Exclusive-OR

来源:互联网 发布:淘宝五分钟内拍下 编辑:程序博客网 时间:2024/05/16 14:29

X0 ~ Xn-1 共n个数,根据给定的信息,给出询问结果。

已知 I a b c 表示Xa ^ Xb = c,I a c表示Xa = c

询问Q K X1...Xk 求X1 ^ ...^ Xk 的结果。

1.令Xn = 0,将Xa = c转变成Xa ^ Xn = c,所以所有已知的数都和Xn在同一棵树(以n为根)

2.在询问时,X1 ^ ... Xk = Xf1 ^ ... Xfk ^ v[1] ^... ^ v[k]。其中Xfi未知,如果根出现的次数为偶数,则可消去,如果为奇数,如果Xfi的根(即Xi)的根为Xn,则数已知,可求,否则,就无法求出。

3.v[i]记录Xi与根Xfi的关系。

4.memset(v,0,sizeof(int) * n)就好了,不一定要到maxn的,特别是要经常初始化的。

只在乎奇偶的话^= 1也不错。

#include <cstdio>

#include <iostream>

#include <cstring>

using namespacestd;


const int maxn =2e5 + 50;


int f[maxn],v[maxn],cnt[maxn];

int n,q;

bool cft = false;


int find(int x)

{

    if(f[x] == x)return x;

    int tmp =f[x];

    f[x] =find(f[x]);

    v[x] ^=v[tmp];

    returnf[x];

}

void init(int n)

{

    memset(v,0, sizeof(int) * (n +1));

    for (int i =0; i <= n; i ++) {

        f[i] = i;

    }

    cft =false;

}

void merge(int a,int b,int c)

{

    int fa =find(a);

    int fb =find(b);

    if(fa == fb) {cft = ((v[a] ^v[b]) != c); return;}

    if(fa > fb)swap(fa,fb);

    f[fa] = fb;

    v[fa] =v[a] ^ v[b] ^ c;

}

void query()

{

    memset(cnt,0, sizeof(int) *n);

    int k,t,ans =0,rt;

    scanf("%d",&k);

    for (int j =0; j < k; j ++) {

        scanf("%d",&t);

        rt = find(t);

        cnt[rt] ^=1;

        ans ^= v[t];

    }

    if(!cft){

        for (int i =0; i < n; i ++) {

            if(cnt[i]) {printf("I don't know.\n");return;}

        }

        printf("%d\n",ans);

    }

}

int main()

{

    int cn =0;

    while (scanf("%d%d",&n,&q) != EOF) {

        getchar();

        if(n ==0 && q ==0) break;

        printf("Case %d:\n",++cn);

        init(n);

        int th =0;

        char op;

        int a =0,b = 0,c =0;

        for (int i =1; i <= q; i ++) {

            scanf("%c",&op);

            if(op =='I')

            {   th ++;

                scanf("%d%d%c",&a,&b,&op);

                if(op ==' '){scanf("%d",&c);getchar();}

                elseif(op == '\n') {c = b,b =n;}

                if(!cft){

                    merge(a,b,c);

                    if(cft)printf("The first %d facts are conflicting.\n",th);

                }

            }

            else {

                query();getchar();

            }

        }

        printf("\n");

    }

    return0;

}