UVa12232 Exclusive-OR(加权并查集)

题意

给出一些事实,有两种情况

X_p = v或者X_p xor X_q = v

需要计算X_1 xor X_2 .... xor X_n的值。如果根据已经的事实,可以计算出则输出结果,否则输出I don't know。在给出的事实中,有可能会有冲突。

思路

使用并查集,使用val(x)来表示x与其父结点的异或值。在使用路径压缩时,val(x)最终会变成x与其根节点的异或值。

对于X_p = v这种情况,可以转成X_p xor X_n = v,在做这种合并时,将Xn作为根结点

可以计算出结果的情况下,在根结点不是Xn时,需要根结点的引用次数为偶数个

#include 

using namespace std;

const int N = 20010;

int p[N];
int val[N];
int n;
int vis[N];

struct Info
{
    string c;
    int p, q, v;
    vector vec;
};

void fastio()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
}

void init()
{
    for (int i = 0; i <= n; i++) {
        p[i] = i;
        val[i] = 0;
    }
}

int find_set(int x) 
{
    if (p[x] == x) {
        return x;
    }
    
    int pa = p[x];
    p[x] = find_set(p[x]);
    val[x] ^= val[pa];
    
    return p[x];
}
int main()
{
    fastio();

#ifndef ONLINE_JUDGE
    ifstream fin("f:\\OJ\\uva_in.txt");
    streambuf* back = cin.rdbuf(fin.rdbuf());
#endif
    
    int q;
    int testCase = 1;
    while (cin >> n >> q) {
        if (n == 0 && q == 0) {
            break;
        }
        
        string line;
        getline(cin, line);
        
        vector infos;
        for (int i = 0; i < q; i++) {
            getline(cin, line);
            stringstream ss(line);
            
            Info info;
            ss >> info.c;
            if (info.c[0] == 'I') {
                vector v;
                int tmp;
                while (ss >> tmp) {
                    v.push_back(tmp);
                }
                
                if (v.size() == 2) {
                    info.p = v[0];
                    info.q = n;
                    info.v = v[1];
                } else {
                    info.p = v[0];
                    info.q = v[1];
                    info.v = v[2];
                }
            } else {
                int k;
                ss >> k;
                for (int i = 0; i < k; i++) {
                    int tmp;
                    ss >> tmp;
                    info.vec.push_back(tmp);
                }
            }
            
            infos.push_back(info);
        }
        
        /*for (size_t i = 0; i < infos.size(); i++) {
            cout << "c:" << infos[i].c << " p:" << infos[i].p << " q:" << infos[i].q << " v:" << infos[i].v << endl;
        }*/
        init();
        cout << "Case " << testCase++ << ":" << endl;
        int facts = 0;
        for (size_t i = 0; i < infos.size(); i++) {
            char ch = infos[i].c[0];
            if (ch == 'I') {
                facts++;
                //cout << "p:" << infos[i].p << " q:" << infos[i].q << endl;
                
                /*for (int i = 0; i <= n; i++) {
                    cout << p[i] << " ";
                }
                cout << endl;*/
                int pa = find_set(infos[i].p);
                int pb = find_set(infos[i].q);
                //cout << "pa:" << pa << " pb:" << pb << endl;
                if (pa == pb) {
                    if ((val[infos[i].p] ^ val[infos[i].q]) != infos[i].v) {
                        cout << "The first " << facts << " facts are conflicting." << endl;
                        break;
                    }
                } else {
                    if (pa == n) swap(pa, pb);
                    p[pa] = pb;
                    val[pa] = val[infos[i].p] ^ val[infos[i].q] ^ infos[i].v;
                }
            } else {
                memset(vis, 0, sizeof(vis));
                int ans = 0;
                for (size_t j = 0; j < infos[i].vec.size(); j++) {
                    int pa = find_set(infos[i].vec[j]);
                    ans ^= val[infos[i].vec[j]];
                    if (pa != n) {
                        vis[pa] ^= 1;
                    }
                }
                
                bool flag = true;
                for (int i = 0; i < n; i++) {
                    if (vis[i]) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    cout << ans << endl;
                } else {
                    cout << "I don't know." << endl;
                }
            }
        }
        cout << endl;
    }
    

#ifndef ONLINE_JUDGE
    cin.rdbuf(back);
#endif

    return 0;
}

 

你可能感兴趣的:(算法设计与分析,OJ,训练指南,算法)