zoukankan      html  css  js  c++  java
  • 【uva12232/hdu3461】带权并查集维护异或值

    题意:

    对于n个数a[0]~a[n-1],但你不知道它们的值,通过逐步提供给你的信息,你的任务是根据这些信息回答问题:
    I P V :告诉你a[P] = V
    I P Q V:告诉你a[P] XOR a[Q] = V
    Q K P1..PK:询问a[P1]^a[P2]^...a[PK]的值
    n<=20000

    题解:
     
    首先看前两个操作:
    第一个操作我们可以新加一个节点a[n]=0,则a[p]=val转化为a[p]^a[n]=val。
    那么所有知道值的点必定都与a[n]在同一个并查集之内。
     
    我们可以用带权并查集,对每个点x维护fa[x],d[x]是a[x]^a[fa[x]]。
    对与第三个操作,我们可以发现p1,p2,...,pk必定在某几个并查集之中。
    如果某个并查集中有奇数个p,那就相当于a[p1]^a[p2]^..a[px] ^ 奇数次a[根](异或一个数偶数次相当于没有异或它)。
    如果根不是a[n],也就是根的值未知,那么必定是不确定答案的。
    否则我们就可以直接算出。

    注意合并的时候如果有一个是a[n]所在集合,要让a[n]为根。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<ctime>
     6 using namespace std;
     7 
     8 const int N=20100;
     9 int n,m,fa[N],d[N],cnt[N],q[N];
    10 char s[10];
    11 
    12 int findfa(int x)
    13 {
    14     if(fa[x]!=x)
    15     {
    16         int xx=fa[x];
    17         fa[x]=findfa(fa[x]);
    18         d[x]=d[x]^d[xx];
    19     }
    20     return fa[x];
    21 }
    22 
    23 int main()
    24 {
    25     freopen("a.in","r",stdin);
    26     freopen("a.out","w",stdout);
    27     char ch;
    28     int x,y,k,p,xx,yy,val,ans,bk,ok,num,T=0;
    29     while(1)
    30     {
    31         scanf("%d%d",&n,&m);
    32         if(!n && !m) break;
    33         printf("Case %d:
    ",++T);
    34         memset(cnt,0,sizeof(cnt));
    35         for(int i=0;i<=n;i++) fa[i]=i,d[i]=0;
    36         num=0;bk=1;
    37         for(int i=1;i<=m;i++)
    38         {
    39             scanf("%s",s);
    40             if(s[0]=='I')
    41             {
    42                 num++;
    43                 scanf("%d%d%c",&x,&y,&ch);
    44                 if(ch==' ') scanf("%d",&val);
    45                 else val=y,y=n;
    46                 if(!bk) continue;
    47                 xx=findfa(x);yy=findfa(y);
    48                 if(xx!=yy)
    49                 {
    50                     if(xx==n) swap(x,y),swap(xx,yy);//debug
    51                     fa[xx]=y;
    52                     d[xx]=val^d[x];
    53                 }
    54                 else if((d[x]^d[y])!=val) {printf("The first %d facts are conflicting.
    ",num);bk=0;}
    55             }
    56             else
    57             {
    58                 scanf("%d",&k);
    59                 for(int j=1;j<=k;j++)
    60                 {
    61                     scanf("%d",&q[j]);
    62                     findfa(q[j]);
    63                     cnt[fa[q[j]]]++;                    
    64                 }
    65                 if(!bk) continue;
    66                 ans=0;ok=1;
    67                 for(int j=1;j<=k;j++)
    68                 {
    69                     x=q[j];
    70                     if(fa[x]!=n && (cnt[fa[x]]&1)) {printf("I don't know.
    ");ok=0;break;}
    71                     ans^=d[x];
    72                 }
    73                 for(int j=1;j<=k;j++) cnt[fa[q[j]]]--;
    74                 if(ok) printf("%d
    ",ans);
    75             }
    76             // printf("i = %d
    ",i);
    77             // for(int j=0;j<n;j++) printf("%d  fa = %d  d = %d
    ",j,fa[j],d[j]);
    78             // printf("
    ");
    79         }
    80         printf("
    ");
    81     }
    82     return 0;
    83 }
     
  • 相关阅读:
    setTimeout,clearTimeout,setInterval,clearInteral详解
    关于JS读取DOM对象(标签)的自定义属性
    jquery.form.js官方插件介绍Form插件,支持Ajax,支持Ajax文件上传
    按回车键切换input鼠标光标
    电压跟随器的作用,以及其中两个电阻的作用?
    阅读RB521S30肖特基二极管的datasheet
    配置linux内核,解决lcd logo和十分钟息屏!
    配置linux,关闭LCD的console控制台输出。
    记录一次编译linux内核或者说编译dtbs的问题!!
    copy_from_user的详细用法!
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/6044206.html
Copyright © 2011-2022 走看看