hdu3234 带权并查集(XOR)

题意:
      给你n个未知的正整数,有三总操作
      I P V            P的值是V
      I P Q V          P XOR Q = V
      Q K x1 x2....xk  求这k个数所有异或后的值
思路:
      带权并查集,感觉这个题目用的很巧,设计到以下知识,a ^ b = c ,a ^ c = b ,b 

^ c = a他们三个是等价的,还有就是a ^ b ^ a = b ,这个题目自己好好画画就出来了,确定好带权并查集后可以虚拟出来一个点,把它做为真实点,就是如果谁的根是他那么这个值就已经确定了,我虚拟的是0点,把其他的点都映射成+1,还有就是这个题目的核心部分就是查询的那个地方,除了确定的点,其他的必须是每个集合都出现了偶数个的时候才能算出来,原因就是“性质不同的数不能乘在一起,要么就是相对位置相乘,要么就是确定的数字相乘,两个相对位置相乘的到的是确定的数字,确定的数字相乘得到的还是确定的数字”,这个题目设计到很多细节,我就不说了,谁做谁知道啊! 还有就是提醒个最坑的地方 a ^ b != c 他和 (a ^ b) != c不是等价的,优先级的原因。其他的做的时候就知道了,今天手残,这个题目做了17次才AC.


#include<stdio.h>
#include<string.h>

#define N 22000

int mer[N] ,Xor[N];
int ss[N];

int finds(int x)
{
   if(x == mer[x]) return x;
   int t = mer[x];
   mer[x] = finds(mer[x]);
   Xor[x] = Xor[x] ^ Xor[t];
   return mer[x];
}

int main ()
{
   int n ,m ,i ,j ,num ,p ,q ,v ,k;
   int n1 ,n2 ,n3 ,cas = 1 ,fact ,stop;
   char str[10] ,c;
   while(~scanf("%d %d" ,&n ,&m) && n + m)
   {
      printf("Case %d:
" ,cas ++);
      for(i = 0 ;i <= n ;i ++)
      mer[i] = i ,Xor[i] = 0;
      for(stop = fact = 0 ,i = 1 ;i <= m ;i ++)
      {
         scanf("%s" ,str);
         if(str[0] == 'I')
         {
            fact ++; int ii = 0;
            while(1)
            {
               scanf("%d%c" ,&num ,&c);
               ii ++;
               if(ii == 1) n1 = num;
               if(ii == 2) n2 = num;
               if(ii == 3) n3 = num;
               if(c == '
') break;
            }
            if(stop) continue;
            if(ii == 2)
            {
               p = n1 + 1 ,v = n2;
               int x = finds(p);
               if(!x)
               {
                  if(Xor[p] == v) continue;
                  stop = 1;
                  printf("The first %d facts are conflicting.
" ,fact ++);
               }
               else
               {
                  mer[x] = 0;
                  Xor[x] = Xor[p] ^ v;
               }
            }
            if(ii == 3)
            {
               p = n1 + 1 ,q = n2 + 1 ,v = n3;
               int x = finds(p) ,y = finds(q);
               if(x == y)
               {
                  if((Xor[p] ^ Xor[q]) == v) continue;
                  stop = 1;
                  printf("The first %d facts are conflicting.
" ,fact ++);
               }
               else
               {
                  if(y)
                  {
                     mer[y] = x;
                     Xor[y] = Xor[p] ^ Xor[q] ^ v;                   
                  }
                  else
                  {
                      mer[x] = y;
                      Xor[x] = Xor[p] ^ Xor[q] ^ v;  
                  }
               }
            }
         }
         else
         {
            scanf("%d" ,&k);
            memset(ss ,0 ,sizeof(ss));
            int sum = 0 ,mk = 0;
            for(j = 1 ;j <= k ;j ++)
            {
               scanf("%d" ,&num);
               num ++;
               ss[finds(num)] ++;
               sum = sum ^ Xor[num];
            }
            for(j = 1 ;j <= n ;j ++)
            if(ss[j] & 1) mk = 1;
            if(stop) continue;
            if(mk) puts("I don't know.");
            else printf("%d
" ,sum);
         }
      }
      puts("");
   }
   return 0;
}
               

原文地址:https://www.cnblogs.com/csnd/p/12062959.html