zoukankan      html  css  js  c++  java
  • Exclusive-OR(带权并查集)

    Exclusive-OR

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 152 Accepted Submission(s): 55
     
    Problem Description
    You are not given n non-negative integers X0, X1, ..., Xn-1 less than 220 , but they do exist, and their values never change.

    I'll gradually provide you some facts about them, and ask you some questions.

    There are two kinds of facts, plus one kind of question:

     
    Input
    There will be at most 10 test cases. Each case begins with two integers n and Q (1 <= n <= 20,000, 2 <= Q <= 40,000). Each of the following lines contains either a fact or a question, formatted as stated above. The k parameter in the questions will be a positive integer not greater than 15, and the v parameter in the facts will be a non-negative integer less than 220. The last case is followed by n=Q=0, which should not be processed.
     
    Output
    For each test case, print the case number on its own line, then the answers, one on each one. If you can't deduce the answer for a particular question, from the facts I provide you before that question, print "I don't know.", without quotes. If the i-th fact (don't count questions) cannot be consistent with all the facts before that, print "The first i facts are conflicting.", then keep silence for everything after that (including facts and questions). Print a blank line after the output of each test case.
     
    Sample Input
    2 6
    I 0 1 3
    Q 1 0
    Q 2 1 0
    I 0 2
    Q 1 1
    Q 1 0
    3 3
    I 0 1 6
    I 0 2 2
    Q 2 1 2
    2 4
    I 0 1 7
    Q 2 0 1
    I 0 1 8
    Q 2 0 1
    0 0
     
    Sample Output
    Case 1:
    I don't know.
    3
    1
    2
    Case 2:
    4
    Case 3:
    7
    The first 2 facts are conflicting.
     
     
    Source
    2009 Asia Wuhan Regional Contest Hosted by Wuhan University
     
    Recommend
    chenrui
     
    /*
    题意:有n个数,但是n个数还没确定,有两种操作:
        I:p v告诉你Xp的值。
        I:p q v告诉你Xp^Xq=v。
        Q:k p1 p2...pk 询问 Xp1^Xp2...^Xpk=?
        如果I操作有矛盾请指出。
    
    初步思路:带权并查集。r[i]数组表示i与根节点的异或值,查询的时候,r[a]^r[b]实际上就是a^b的值,因为,父节点的已经
        已经异或掉了,很显然如果是奇数个肯定是求不出来的
    */
    #include<bits/stdc++.h>
    using namespace std;
    int n,m,k;
    char op[100];
    int num[20005];//存放各种数据
    int father[20005];//存储i的父节点
    int r[20005];//存放i与父节点的异或
    int vis[20005];//记录访问过的点
    int ca=1;
    int u,v,c;
    char str[100];
    int times=0;//用来记录I操作进行了几次
    int findx(int x){
        if(x!=father[x])
        {
            int fx = father[x];
            father[x] = findx(father[x]);
            r[x]^=r[fx];
        }
        return father[x];
    }
    bool Union(int x,int y,int z){
        int fx=findx(x);
        int fy=findx(y);
        if(fx==fy){
            if((r[x]^r[y])!=z)
                return false;
            return true;
        }
        if(fx==n) swap(fx,fy);
        father[fx]=fy;
        r[fx] = r[x]^r[y]^z;
        return true;
    }
    int query(){
        memset(vis,0,sizeof vis);
        int ans=0;
        for(int i=0;i<k;i++){
            if(vis[i]) continue;
            int cnt=0;
            int root=findx(num[i]);
            for(int j=i;j<k;j++) {
                if(!vis[j] && root == findx(num[j])){
                    vis[j] = 1;
                    cnt++;
                    ans^=r[num[j]];
                }
            }
            if(root!=n&&(cnt&1)){
                return -1;
            }
        }
        return ans;
        
    }
    void init(){
        memset(r,0,sizeof r);
        for(int i=0;i<=n;i++){
            father[i]=i;
        }
        times=0;
    }
    int main(){
        // freopen("in.txt","r",stdin);
        while(scanf("%d%d",&n,&m)!=EOF&&(n+m)){
            init();
            printf("Case %d:
    ",ca++);
            bool flag=false;//表示命令的正确性
            for(int i=0;i<m;i++){
                scanf("%s",op);
                // cout<<op<<" ";
                getchar();
                if(op[0]=='I'){
                    times++;
                    gets(str);
                    // cout<<str<<endl;
                    if(flag) continue;
                    int cur=0;
                    for(int i=0;str[i];i++){
                        if(str[i]==' ') cur++;
                    }
                    if(cur==1){//u c
                        sscanf(str,"%d%d",&u,&c);
                        v=n;
                        // cout<<u<<" "<<c<<endl;
                    }else{//u v c
                        sscanf(str,"%d%d%d",&u,&v,&c);
                        // cout<<u<<" "<<v<<" "<<c<<endl;
                    }
                    if(!Union(u,v,c))
                    {
                        printf("The first %d facts are conflicting.
    ",times);
                        flag = true;
                    }
                }else{
                    scanf("%d",&k);
                    // cout<<k<<" ";
                    for(int i=0;i<k;i++){
                        scanf("%d",&num[i]);
                        // cout<<num[i]<<" ";
                    }
                    // cout<<endl;
                    if(flag) continue;
                    int ans = query();
                    if(ans == -1)
                        printf("I don't know.
    ");
                    else
                        printf("%d
    ",ans);
                }
            }
            // for(int i=0;i<n;i++){
                    // cout<<father[i]<<" ";
                // }
                // cout<<endl;
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    播放m3u文件时不能时时更新的问题
    Oracle视图详解
    Oracle视图的作用与安全性
    Ext GridPanel 表头合并
    [AJAX] 001 AJAX核心操作
    [Java] 系统环境变量配置
    [AJAX] 002 AJAX异步验证
    判断文章/帖子操作权限
    让Tee 7.x版本和FastReport 3.x版本共存
    mysql基本语句
  • 原文地址:https://www.cnblogs.com/wuwangchuxin0924/p/6430656.html
Copyright © 2011-2022 走看看