并查集+

食物链

带权并查集

#include<iostream>

using namespace std;

const int N = 100010;

int p[N],d[N];
int n,k;
int res = 0;

int find(int x){
    if(p[x] != x){
        int rot = find(p[x]);
        d[x] += d[p[x]];
        p[x] = rot;
    }

    return p[x];
}

int main(){
    cin >> n >> k;

    for(int i = 1;i <= n;i ++) p[i] = i;

    while(k --){
        int op,a,b;
        cin >> op >> a >> b;

        if(a > n || b > n) res ++;
        else{
            int pa = find(a),pb = find(b);

            if(op == 1){
                if(pa == pb && (d[a] - d[b]) % 3) res ++;
                else if(pa != pb){
                    p[pa] = pb;
                    d[pa] = d[b] - d[a];
                }
            }else{
                if(pa == pb && (d[a] - d[b] - 1) % 3) res ++;
                else if(pa != pb){
                    p[pa] = pb;
                    d[pa] = d[b] - d[a] + 1;
                }
            }
        }
    }

    cout << res;
}

拓展域

#include<iostream>

using namespace std;

const int N = 50010;

int p[N * 3];
int n,k;
int res = 0;

int find(int x){
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

void meg(int a,int b){
    p[find(a)] = find(b);
}

int main(){
    cin >> n >> k;

    for(int i = 1;i <= n * 3;i ++) p[i] = i;

    while(k --){
        int op,a,b;
        cin >> op >> a >> b;

        if(a > n || b > n) res ++;
        else{
            int pa1 = find(a),pa2 = find(a + n),pa3 = find(a + 2 * n);
            int pb1 = find(b),pb2 = find(b + n),pb3 = find(b + 2 * n);
            if(op == 1){
                if(pa1 == pb2 || pa1 == pb3) res ++;
                else{
                    meg(pa1,pb1);
                    meg(pa2,pb2);
                    meg(pa3,pb3);
                }
            }else{
                if(pa1 == pb1 || pa1 == pb3) res ++;
                else{
                    meg(pa1,pb2);
                    meg(pa2,pb3);
                    meg(pa3,pb1);
                }
            }
        }
    }

    cout << res;
}

奇偶游戏

带权并查集

有序离散化(排序、去重、二分)

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 100010;

int n,m;
int p[N],d[N];
int alls[N];
struct query{
    int l,r;
    int sex;
} q[N];

int find(int x){
    if(p[x] != x){
        int rot = find(p[x]);
        d[x] ^= d[p[x]];
        p[x] = rot;
    }

    return p[x];
}

void init(){
    cin >> n >> m;

    int t = 0;
    for(int i = 0;i < m;i ++){
        string s;
        cin >> q[i].l >> q[i].r >> s;

        if(s == "odd") q[i].sex = 1;
        else q[i].sex = 0;

        alls[++ t] = q[i].l;
        alls[++ t] = q[i].r;
    }

    sort(alls + 1,alls + 1 + t);
    n = unique(alls + 1,alls + 1 + t) - alls - 1;

    for(int i = 1;i <= n;i ++) p[i] = i;
}

int main(){
    init();

    int res = m;
    for(int i = 0;i < m;i ++){
        int l = lower_bound(alls + 1,alls + 1 + n,q[i].l - 1) - alls; 
        int r = lower_bound(alls + 1,alls + 1 + n,q[i].r) - alls;

        int pl = find(l),pr = find(r);

        if(pl == pr){
            if((d[l] ^ d[r]) != q[i].sex){
                res = i;
                break;
            }
        }else{
            p[pl] = pr;
            d[pl] = d[l] ^ d[r] ^ q[i].sex;
        }
    }

    cout << res;
}

无序离散化

#include<iostream>
#include<unordered_map>

using namespace std;

const int N = 100010;

int p[N],d[N];
int n,m;
unordered_map<int,int> s;

int find(int x){
    if(p[x] != x){
        int rot = find(p[x]);
        d[x] ^= d[p[x]];
        p[x] = rot;
    }

    return p[x];
}

int get(int x){
    if(!s[x]) s[x] = ++n;

    return s[x];
}

int main(){
    cin >> n >> m;
    n = 0;
    int res = m;

    for(int i = 1;i <= m;i ++){
        int a,b;
        string c;
        cin >> a >> b >> c;

        a = get(a - 1),b = get(b);
        //动态初始化 cite(https://www.acwing.com/solution/content/58761/)
        if(!p[a]) p[a] = a;
        if(!p[b]) p[b] = b;
        int pa = find(a),pb = find(b);
        int t = (c == "even" ? 0 : 1);

        if(pa == pb){
            if((d[a] ^ d[b]) != t){
                res = i - 1;
                break;
            }
        }else{
            p[pa] = pb;
            d[pa] = d[a] ^ d[b] ^ t;
        }
    }

    cout << res;
}

无序离散化 + 扩展域

#include<iostream>
#include<unordered_map>

using namespace std;

const int N = 10010;

int p[N * 2];
int n,m;
unordered_map<int,int> alls;
int len = 0;

int find(int x){
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int get(int x){
    if(!alls[x]) alls[x] = ++ len;
    return alls[x];
}

void meg(int x,int y){
    p[find(x)] = find(y);
}

int main(){
    cin >> n >> m;

    for(int i = 1;i <= N * 2;i ++) p[i] = i;

    int res = m;
    for(int i = 0;i < m;i ++){
        int a,b;
        string c;
        cin >> a >> b >> c;

        a = get(a - 1),b = get(b);
        int pa1 = find(a),pa2 = find(a + N);
        int pb1 = find(b),pb2 = find(b + N);

        if(c == "even"){
            if(pa1 == pb2){
                res = i;
                break;
            }else{
                meg(pa1,pb1);
                meg(pa2,pb2);
            }
        }else{
            if(pa1 == pb1){
                res = i;
                break;
            }else{
                meg(pa1,pb2);
                meg(pa2,pb1);
            }
        }
    }

    cout << res;
}
posted @ 2021-11-15 21:21  Xuuxxi  阅读(58)  评论(0)    收藏  举报