zoukankan      html  css  js  c++  java
  • hdu3234 ExclusiveOR

    题意:

    题目将以这样的形式进行提供已知条件或者提问,

    分析:首先可以想到的是可以用并查集来做。

    题目的是x1^x2^x3^……式子的值,

    那么首先就要考虑俩个问题了:

    1):如何记录x[]元素之间的关系

    2):怎样传递元素之间的关系

    这里我们注意到异或运算的性质:

    对于a,b,c有:a xor b == c 和 a xor c == b 和 b xor c == a 等价,a^a==0

    因此:我们用r[]数组保存该元素与根节点异或运算的关系;

    接下来,为了方便处理,我们定义一个虚点xn,r[xn]=0,这样,只要根节点为xn的元素,这对于的具体也是已知的,同时,r[]的值就是其具体的值;而且,有一个好处就是,当进行I p v 操作时,相当于合并Union(p,n,v);

    在压缩路径过程中,用r[x]^=r[f[x]] 求出与根节点的关系;

    在判断能否计算出式子的值时,我们发现,根节点不为xn的元素,该集合必须出现偶数个的元素,否则该式子的具体值无法计算;

    接下来就是读入数据的问题,额,我的方法比较笨……

    基本已经可以实现了,看代码吧:

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    int f[20010],r[20010],n;
    int map[20010];
    int xp[20],ans;
    void init()
    {
    	for(int i=0;i<=n;i++)
    	{
    		f[i]=i;
    		r[i]=0;
    	}
    }
    int find(int x)
    {
    	if(x==f[x])
    		return x;
    	int t=find(f[x]);
    	r[x]^=r[f[x]];//根据x与父节点的关系求出x与根节点的关系
    	f[x]=t;
    	return f[x];
    }
    bool Union(int x,int y,int k)
    {
    	int a=find(x);
    	int b=find(y);
    	if(a==b)
    	{
    		if((r[x]^r[y])==k)
    			return true;
    		return false;
    	}
    	if(a==n)
    		swap(a,b);
    		f[a]=b;
    		r[a]=r[x]^r[y]^k;
    	return true;
    }
    bool query(int m)
    {
    	memset(map,0,sizeof(map));
    	for(int i=0;i<m;i++)
    	{
    		map[find(xp[i])]++;
    		ans^=r[xp[i]];
    	}
    	int flag=0;
    	for(int i=0;i<m;i++)
    	{
    		int t=find(xp[i]);
    		if(map[t]%2!=0 && t!=n)
    		{flag=1;break;}
    	}
    	if(flag)
    		return false;
    	 return true;
    
    }
    int main()
    {
    	char s[2],c;
    	int a,b,v,Q,cas=0;	
    	while(scanf("%d %d",&n,&Q)==2 &&(n||Q))
    	{
    		init();
    		printf("Case %d:\n",++cas);
    	int fact=0,flag=0;
    	while(Q--)
    	{
    		scanf("%s%d%d",s,&a,&b);
    		if(s[0]=='I')
    		{
    			fact++;
    			c=getchar();
    			if(c==' ')
    			{
    				scanf("%d",&v);
    				if(flag)continue;
    				if(!Union(a,b,v))
    				{
    					printf("The first %d facts are conflicting.\n",fact);
    					flag=1;
    				}
    			}
    			else
    				{
    					if(flag)continue;
    					if(!Union(a,n,b))
    					{
    					  printf("The first %d facts are conflicting.\n",fact);
    					  flag=1;
    				    }
    			    }
    		}
    		else 
    		{
    		    xp[0]=b;
    			for(int i=1;i<a;i++)
    				scanf("%d",&xp[i]);//额,这里有点多此一举
    			if(flag)continue;
    			ans=0;
    			if(query(a))
    				printf("%d\n",ans);
    			else printf("I don't know.\n");
    		}
    	 }
    	printf("\n");
    	}
    	return 0;
    }
    
    
    
  • 相关阅读:
    [LeetCode] Best Time to Buy and Sell Stock III
    [LeetCode] Implement strStr()
    [LeetCode] Wildcard Matching
    [LeetCode] Gray Code
    [LeetCode] Divide Two Integers
    [LeetCode] Flatten Binary Tree to Linked List
    [LeetCode] Binary Tree Maximum Path Sum
    [TopCoder][SRM] SRM 562 DIV 2
    推荐博客文章
    检测两点所确定直线上的像素坐标
  • 原文地址:https://www.cnblogs.com/nanke/p/2220998.html
Copyright © 2011-2022 走看看