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;
    }
  • 相关阅读:
    Windows下安装Redis服务、搭建简单Redis主从复制
    windows下Redis主从复制配置(报错:Invalid argument during startup: unknown conf file parameter : slaveof)
    C#设计模式之控制反转即依赖注入-微软提供的Unity
    C#设计模式之控制反转即依赖注入-Spring.NET
    MongoDB 性能优化
    MongoDB 副本集和C#交互,简单测试
    分布式文档存储数据库(MongoDB)副本集配置
    文件比对工具(Beyond Compare)
    C# 通过WebService方式 IIS发布网站 上传文件到服务器
    3_11_MSSQL课程_ 视图和临时表
  • 原文地址:https://www.cnblogs.com/wuwangchuxin0924/p/6430656.html
Copyright © 2011-2022 走看看