UVA -2232(并查集 + 位运算)
来源:互联网 发布:软件设计方案和要求 编辑:程序博客网 时间:2024/05/22 14:34
首先,说些关于异或的信息,异或满足交换律和结合律,这为用并查集创造了条件。
又有 a^b= x, b^c=y; a^c=x^y;
本题目有三种操作,两种存,一种查。对于建立并查集时候要维护两个信息,第一个就是当前节点和root异或的值,当前集合是否存在已知量(之需要确保根部知道这个情况就可以,一个集合里有一个一致,那么该集合任一元素都可以通过异或得到)
查的时候分为两种情况,第一种该元素所在集合没有已知值得点,那么这个集合里的元素在要查集合里有且仅有两个该集合才有解。
剩下的元素,一个个算就可以了。
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <set>#include <algorithm>using namespace std;#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)const int maxn = 51000;int p[maxn],d[maxn],hav[maxn];int find(int x){ if(p[x] == x) return x; if(hav[p[x]]==-1){ hav[p[x]]=hav[x]; } int root=find(p[x]); d[x]^=d[p[x]]; return p[x]=root;}int a[maxn],n,m,val[maxn];void init(){ rep(i,n){ p[i]=i; d[i]=0; hav[i]=-1; }}char str[maxn];void cal(int& cnt){ int len = strlen(str); rep(i,len){ if(isdigit(str[i])){ int j,num=0; for(j=i;j<len;j++){ if(!isdigit(str[j])) break; num=num*10+str[j]-'0'; } a[cnt++]=num; i=j; } }}int cmp(int i,int j){ return find(i)<find(j);}int main (){ int kase=1; while(scanf("%d %d",&n,&m)==2&&n){ printf("Case %d:\n",kase++); init(); gets(str); int ok = 1,counter=0; rep(gg,m){ gets(str); if(!ok) continue; int cnt = 0; cal(cnt); if(str[0]=='I'){ counter++; if(cnt == 2){ int px=find(a[0]); if(hav[px]!=-1){ find(hav[px]); if( (val[hav[px]]^d[hav[px]]^d[a[0]])!=a[1]){ ok = 0; } } else { hav[px] = a[0]; val[a[0]] = a[1]; } } else{ int px=find(a[0]),py=find(a[1]); if(px==py){ if((d[a[0]]^d[a[1]])!=a[2]) ok = 0; } else { d[px]=(d[a[0]]^a[2]^d[a[1]]); p[px]=py; find(px); } } } else { int hav_ans = 1,res=0; sort(a+1,a+cnt,cmp); for(int i=1;i<cnt;i++){ int px=find(a[i]); if(hav[px]==-1){ int ju[2]={0}; if(i+1<cnt&&find(a[i+1])==px) ju[0]=1; if(i+2>=cnt||(i+2<cnt&&find(a[i+2])!=px)) ju[1]=1; if(ju[0]&&ju[1]) { res = (res^d[a[i]]^d[a[i+1]]); i+=1; } else hav_ans = 0; } else { find(hav[px]); res=res^(val[hav[px]]^d[hav[px]]^d[a[i]]); } if(!hav_ans) break; } if(!hav_ans) printf("I don't know.\n"); else printf("%d\n",res); } if(!ok) printf("The first %d facts are conflicting.\n",counter); } printf("\n"); } return 0;}
0 0
- UVA -2232(并查集 + 位运算)
- UVa 10158 并查集+位操作
- poj 1164 The Castle 位运算+并查集/搜索
- [NOIP模拟题][位运算][建模][并查集]
- 【APIO2011T1】方格染色-并查集+位运算推导
- uva 793 并查集
- uva 11503 并查集
- uva 11987 并查集
- Friends+uva+并查集
- UVA 10608并查集
- uva 10608(并查集)
- uva 10158(并查集)
- uva 1493(并查集)
- uva 459 并查集
- UVa 10608 并查集
- 【UVA 11987】并查集
- uva 11987 并查集
- hdu 1198 Farm Irrigation(并查集强大无比的位运算)
- UISegmentedController 使用以及代码!
- 简单自定义View圆形呼吸效果
- [译] 关于CSS中的float和position
- 我希望终点是爱琴海
- 面试小记:关于数组和指针的一个笑话
- UVA -2232(并查集 + 位运算)
- Terminal 命令记录
- 10375 - Choose and divide
- linux中如何设置DHCP
- C++实现快速排序(源代码)
- java取得项目工程---获取文件的相对路径问题---getResource()和getResourceAsStream以及路径问题
- 第一题(equals和hashCode的重写)
- 修改Intel 无线网卡遇到的问题
- 删除表中重复的数据