UVA12232 Exclusive-OR
原题链接:UVA12232 Exclusive-OR - 洛谷 或者 Exclusive-OR - UVA 12232 - Virtual Judge
题解:
带权并查集处理异或运算。
首先,对于第二种情况,I a b v 我们可以将a,b连起来形成一个并查集,同时用一个value数组存储当前节点异或头节点的 的值,此时我们关注的就是不同头节点连接时value数组的更新。
我们思考此时有个一条输入 I a b v ;a 对应的头节点为La,b对应头节点为Lb,假设La挂到Lb上,则
value[La]=value[a]^value[b]^v=a^La ^ b^Lb ^ a^b = La^Lb
这时我们就推出了不同集合之间的更新关系。
接着,我们处理赋值情况,显而易见的是,当一个集合内的一个值确定,那么集合内的其他值都确定(因为我们知道他们的异或关系),这里只需要设置一个虚拟节点即可。
最后,查询过程,如果此时读入一个虚拟节点内的值,那么我们知晓其确切的值,无需处理;但是如果读入的是其余集合内的值,假设为 ai 那么我们只能知晓 ai^fa[ai] 的值,我们不难发现要利用当前集合内的另一个值将fa[ai]的影响消除。
因此,我们得到结论,虚拟节点集合内直接取出对应value,其余集合内要取偶数个才能得到答案。得解。
PS:这道题输出有点坑,首先 I don't know. 中 ‘ 得是英文状态下的;其次,每一组输出后面要额外多一行空行。
code:
#include<bits/stdc++.h> using namespace std; const int N=2e4+5; int fa[N],value[N]; int n,q,t=0; int find_dsu(int tree){ if (tree!=fa[tree]){ int t=fa[tree]; fa[tree]=find_dsu(t); value[tree]^=value[t]; } return fa[tree]; } void union_dsu(int l,int r,int v){ int lf=find_dsu(l),rf=find_dsu(r); if (lf==n){ fa[rf]=n; value[rf]=(value[l]^value[r]^v); // cout<<rf<<" "<<value[l]<<" "<<value[r]<<" "<<v<<"\n"; return; } if (rf==n){ fa[lf]=n; value[lf]=(value[l]^value[r]^v); return; } fa[lf]=rf; value[lf]=(value[l]^value[r]^v); } int main(){ // freopen("input.txt","r",stdin); string s; while (cin>>n>>q){ if (n==0 && q==0) break; cout<<"Case "<<++t<<":\n"; for (int i=0;i<=n;i++){ fa[i]=i; value[i]=0; } int now_q=0; bool is_print=true; while(q--){ cin>>s; if (s[0]=='I'){ getline(cin,s); s=s+" "; int cnt_s=s.size(); now_q++; int a[3]={0,0,0},l=0; for (int i=1;i<cnt_s;i++){ if (s[i]==' '){ l++; } else{ a[l]=a[l]*10+s[i]-'0'; } } // for (int i=0;i<l;i++) cout<<a[i]<<" "; // cout<<"\n"; if (l==2){ int f=find_dsu(a[0]); if (f!=n) union_dsu(n,a[0],a[1]); else if (value[a[0]]!=a[1]){ cout<<"The first "<<now_q<<" facts are conflicting.\n"; is_print=false; } } else{ int lf=find_dsu(a[0]),rf=find_dsu(a[1]); if (lf!=rf) union_dsu(a[0],a[1],a[2]); else if ((value[a[0]]^value[a[1]])!=a[2]){ cout<<"The first "<<now_q<<" facts are conflicting.\n"; is_print=false; } } } else{ // for (int i=0;i<=n;i++){ // cout<<i<<" "<<fa[i]<<" "<<value[i]<<"\n"; // } int k; cin>>k; int ans=0; int now; map<int ,int > num; for (int i=1;i<=k;i++){ cin>>now; int f=find_dsu(now); if (f!=n) num[f]++; ans^=value[now]; } if (is_print==false) continue; bool bol=true; for (auto it : num){ if (it.second%2) bol=false; } if (bol) cout<<ans<<"\n"; else cout<<"I don't know.\n"; } } cout<<"\n"; } return 0; }
浙公网安备 33010602011771号