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;
}

 

posted @ 2025-04-01 15:50  黑屿白  阅读(12)  评论(0)    收藏  举报