• POJ 1182 食物链


    题目链接:POJ 1182 食物链

    题目大意:

    题解:

    并查集+思维

    开了三倍大小的标记数组来表示三个物种,\(1\)\(n\)\(A\)物种,\(n+1\)\(2 \times n\)\(B\)物种,\(2 \times n + 1\)\(3 \times n\)\(C\)物种。
    如果\(u\)\(v\),则相对的\(u+n\)\(v\)为一个物种,\(u+2\times n\)\(v + n\)为一个物种,\(u\)\(v + 2\times n\)为一个物种。
    通过并查集关联同一物种。

    #include <iostream>
    #include <cstdio>
    #include <ctype.h>
    using namespace std;
    #define MAXN 100010
    #define INF 100000000
    #define ll long long
    
    ll read() {     // fast read
        ll ans = 0; int f = 1;  char x = getchar();
        while (!isdigit(x)) {
            if (x == '-')
                f = -1;
            x = getchar();
        }
        while (isdigit(x)) {
            ans = (ans << 3) + (ans << 1) + (x ^ 48);
            x = getchar();
        }
        return ans * f;
    }
    
    int fa[150050], n, k, act, u, v, ans;
    
    int find(int x) {   // find father
        return fa[x] == x ? x : fa[x] = find(fa[x]);
    }
    
    int main() {
        n = read(), k = read();
        for (int i = 1; i <= n; ++i) {
            fa[i] = i;
            fa[i + n] = i + n;
            fa[i + n * 2] = i + n * 2;
        }
        while (k--) {
            act = read(), u = read(), v = read();
            if (u > n || v > n) {
                ans++;
                continue;
            }
            else if (act == 1) {
                if (find(u) == find(v + n) || find(v) == find(u + n)) {
                    ans++;
                }
                else {  // same father
                    fa[find(u)] = find(v);
                    fa[find(u + n)] = find(v + n);
                    fa[find(u + n * 2)] = find(v + n * 2);
                }
            }
            else {
                if (find(u) == find(v + n) || find(u) == find(v)) {
                    ans++;
                }
                else {  // u -> v
                    fa[find(u + n)] = find(v);
                    fa[find(u + n * 2)] = find(v + n);
                    fa[find(u)] = find(v + n * 2);
                }
            }
        }
        cout << ans;
        return 0;
    }
    

    带权并查集

    // 带权并查集
    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    int f[50005], d[50005], n, k, d1, x, y, ans;
    
    int find(int x) {
        if (x != f[x]) {
            int xx = f[x];
            f[x] = find(f[x]);
            d[x] = (d[x] + d[xx]) % 3;
        }
        return f[x];
    }
    
    int main() {
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n; i++) {
            f[i] = i;
            d[i] = 0;
        }
        for (int i = 1; i <= k; i++) {
            scanf("%d%d%d", &d1, &x, &y);
            if ((d1 == 2 && x == y) || (x > n || y > n)) {
                ans++;
                continue;
            }
            if (d1 == 1) {
                if (find(x) == find(y)) {
                    if (d[x] != d[y]) ans++;
                } else {
                    d[f[x]] = (d[y] - d[x] + 3) % 3;
                    f[f[x]] = f[y];
                }
            }
            if (d1 == 2) {
                if (find(x) == find(y)) {
                    if (d[x] != (d[y] + 1) % 3) ans++;
                } else {
                    d[f[x]] = (d[y] - d[x] + 4) % 3;
                    f[f[x]] = f[y];
                }
            }
        }
        printf("%d\n", ans);
        return 0;
    }
    
  • 相关阅读:
    linux环境下的makefile文件的编写(zz)
    linux 中vim的退格键的使用问题
    Design Complier Synthesis Script Templet
    Synthesis Summary 逻辑综合总结
    .net加密
    timestamp (TransactSQL) 时间戳
    ADO.NET连接池
    ASP.NET Web数据控件
    高效的读取二进制数据
    GridView
  • 原文地址:https://www.cnblogs.com/IzumiSagiri/p/15860615.html
Copyright © 2020-2023  润新知