hdu 3234 Exclusive-OR (并查集+异或性质)

Exclusive-OR

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2177    Accepted Submission(s): 603

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

题意:

有n(n<=20000)个未知的整数X0,X1,X2Xn-1,有以下Q个(Q<=40000)操作:

I p v :告诉你Xp=v

I p q v :告诉你Xp ^ Xq=v

Q k p1 p2 … pk : 询问 Xp1 Xor Xp2 .. Xor Xpk, k不大于15。

如果当前的I跟之前的有冲突的话,跳出

思路:

并查集,每个节点记录与根节点的异或偏移量,一个集合内如果有一个知道值了的话,这个集合里面都能知道值,(可以标记根是否已经得到值,或者像网上大部分人的做法,虚拟出一个节点n,值为0,将I操作统一)查询时,如果一个未知集合出现了偶数个,那么可以得到其值,u^root^v^root=u^v,如果出现奇数次,那么不能得到。Merge的时候有个小坑,见代码。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#include<sstream>
#define maxn 20005
#define MAXN 100005
#define mod 100000000
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-8
typedef long long ll;
using namespace std;

int n,m,ans,cnt,tot,flag;
int pre[maxn],px[maxn],val[maxn],vis[maxn];
vector<int>root,q[16];
char s[5],buff[100];

int Find(int x)
{
    if(x==pre[x]) return x;
    int r=pre[x];
    pre[x]=Find(pre[x]);
    px[x]=px[r]^px[x];
    return pre[x];
}
bool Merge(int u,int v,int w)
{
    int x=Find(u),y=Find(v);
    if(x!=y)
    {
        if(vis[x]||vis[y])// 如果有集合知道值 必须以知道值集合的根为根
        {
            if(!vis[y]) swap(x,y);
        }
        pre[x]=y;
        px[x]=w^px[u]^px[v];
    }
    else
    {
        if((px[u]^px[v])!=w) return false ;
    }
    return true ;
}
void update()
{
    int u,v,w;
    cnt++;
    gets(buff);
    stringstream si;
    si.clear(); si.str(buff);
    si>>u; si>>v;
    if(si>>w)
    {
        u++,v++;
        if(flag) return ;
        if(!Merge(u,v,w))
        {
            flag=1;
            printf("The first %d facts are conflicting.\n",cnt);
        }
    }
    else
    {
        if(flag) return ;
        u++;
        int r=Find(u);
        if(vis[r])
        {
            if(val[r]!=(v^px[u]))
            {
                flag=1;
                printf("The first %d facts are conflicting.\n",cnt);
            }
        }
        else
        {
            vis[r]=1;
            val[r]=v^px[u];
        }
    }
}
void query()
{
    int i,j,u,v,k,r,flg;
    scanf("%d",&k);
    root.clear();
    for(i=0;i<k;i++) q[i].clear();
    for(i=1; i<=k; i++)
    {
        scanf("%d",&u);
        u++;
        int r=Find(u);
        flg=0;
        for(j=0;j<root.size();j++)
        {
            if(r==root[j])
            {
                flg=1;
                q[j].push_back(u);
                break ;
            }
        }
        if(!flg)
        {
            root.push_back(r);
            q[root.size()-1].push_back(u);
        }
    }
    if(flag) return ;
    flg=0;
    int res=0;
    for(i=0;i<root.size();i++)
    {
        if(vis[root[i]])
        {
            for(j=0; j<q[i].size(); j++)
            {
                res^=(px[q[i][j]]^val[root[i]]);
            }
        }
        else
        {
            if(q[i].size()%2==1)
            {
                flg=1;
                break ;
            }
            else
            {
                for(j=0; j<q[i].size(); j+=2)
                {
                    u=px[q[i][j]]^px[q[i][j+1]];
                    res^=u;
                }
            }
        }
    }
    if(flg) printf("I don't know.\n");
    else printf("%d\n",res);
}
int main()
{
    int i,j,t,u,v,w,test=0;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0) break ;
        for(i=1; i<=n; i++)
        {
            pre[i]=i;
            px[i]=vis[i]=0;
        }
        flag=cnt=0;
        printf("Case %d:\n",++test);
        for(i=1; i<=m; i++)
        {
            scanf("%s",s);
            if(s[0]=='I') update();
            else query();
        }
        puts("");
    }
    return 0;
}

hdu 3234 Exclusive-OR (并查集+异或性质),布布扣,bubuko.com

时间: 2024-11-08 13:48:52

hdu 3234 Exclusive-OR (并查集+异或性质)的相关文章

HDU 4496 D-City (并查集)

题意:给你n个点m条边,问删除前i条边后有多少个连通分块. 思路:从后往前操作,从后往前添加i条边等于添加完m条边后删掉前m-i条边,可知刚开始没有边,所以sum[m]=n; #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <math.h> #define M 100010

hdu 1811Rank of Tetris (并查集 + 拓扑排序)

1 /* 2 题意:这些信息可能有三种情况,分别是"A > B","A = B","A < B",分别表示A的Rating高于B,等于B,小于B. 3 4 现在Lele并不是让你来帮他制作这个高手榜,他只是想知道,根据这些信息是否能够确定出这个高手榜,是的话就输出"OK". 5 否则就请你判断出错的原因,到底是因为信息不完全(输出"UNCERTAIN"),还是因为这些信息中包含冲突(输出&quo

HDU 1232 畅通工程(并查集)

畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 30485    Accepted Submission(s): 16013 Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇间都可以实现交通(但不一定有

HDU 2017 Code Lock (并查集的应用+快速幂)

链接:HDU 3461 题目大意: 题目的大意是一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个.再给你M个区间[L,M],表示该区间的字母可以一起同步"增加"(从'a'变为'b'为增1,'z'增1为'a').假如一组密码按照给定的区间进行有限次的"增加"操作后可以变成另一组密码,那么我们认为这两组密码是相同的.该题的目标就是在给定N.M和M个区间的前提下计算有多少种不同的密码. 根据题意,如果一个可调整的区间都没有的话,答案应该是26

HDU 4775 Infinite Go(并查集,模拟)

HDU 4775 Infinite Go 题目链接 题意:围棋,两人轮流走,如果有一链被围死,就会被吃掉,问下完后最后黑色和白色各剩多少棋 思路:模拟,利用一个并查集来保存链,然后并记录下周围有多少个空格,然后去模拟,注意几个点,就是删除的时候,要把空格还回去,还有边界的位置是也算被围死的 代码: #include <stdio.h> #include <string.h> #include <queue> #include <map> using name

HDU 1198-Farm Irrigation(并查集)

Farm Irrigation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5820    Accepted Submission(s): 2523 Problem Description Benny has a spacious farm land to irrigate. The farm land is a rectangle

HDU 1198 Farm Irrigation (并查集)

Farm Irrigation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5809    Accepted Submission(s): 2516 Problem Description Benny has a spacious farm land to irrigate. The farm land is a rectangle,

hdu 3047 Zjnu Stadium 并查集高级应用

Zjnu Stadium Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1631    Accepted Submission(s): 616 Problem Description In 12th Zhejiang College Students Games 2007, there was a new stadium built

hdu 3172 Virtual Friends (并查集 + 字典树)

题目: 链接:点击打开链接 题意: 输入n,给出n行数据,每行有两个字符串,输出关系网络中朋友的个数,n行. 思路: 代码: #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int N = 22; const int M = 200020; struct node { int c; node *chil