• acwing算法提高之数据结构--并查集


    1 介绍

    本专题用来记录并查集相关的题目。

    并查集模板

    //初始化
    for (int i = 1; i <= n; ++i) { //n为结点数目
    	p[i] = i;
    }
    
    //查找
    find(int x) {
    	if (p[x] != x) p[x] = find(p[x]);
    	return p[x];
    }
    
    //合并
    int pa = find(a);
    int pb = find(b);
    if (pa != pb) {
    	p[pa] = pb;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2 训练

    题目11250格子游戏

    C++代码如下,

    #include 
    #include 
    #include 
    
    using namespace std;
    
    const int N = 210;
    int n, m;
    int p[N * N];
    
    int find(int x) {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }
    
    int main() {
        cin >> n >> m;
        for (int i = 0; i < n * n; ++i) p[i] = i;
        
        for (int i = 1; i <= m; ++i) {
            int x, y;
            char op;
            cin >> x >> y >> op;
            int a, b;
            if (op == 'D') {
                a = (x - 1) * n + y - 1;
                b = x * n + y - 1;
            } else {
                a = (x - 1) * n + y - 1;
                b = (x - 1) * n + y;
            }
            int pa = find(a);
            int pb = find(b);
            if (pa == pb) {
                cout << i << endl;
                return 0;
            } else {
                p[pa] = pb;
            }
        }
        
        cout << "draw" << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    题目21252搭配购买

    C++代码如下,

    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    const int N = 10010;
    int n, m, W;
    int c[N], w[N];
    int p[N];
    int sc[N]; //每个连通块的总价格,只针对根结点
    int sw[N]; //每个连通块的总价值
    int f[N];
    
    int find(int x) {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }
    
    int main() {
        cin >> n >> m >> W;
        for (int i = 1; i <= n; ++i) {
            cin >> c[i] >> w[i];
        }
        
        for (int i = 1; i <= n; ++i) {
            p[i] = i;
            sc[i] = c[i];
            sw[i] = w[i];
        }
        
        for (int i = 1; i <= m; ++i) {
            int a, b;
            cin >> a >> b;
            int pa = find(a);
            int pb = find(b);
            if (pa != pb) {
                p[pa] = pb;
                sc[pb] += sc[pa];
                sw[pb] += sw[pa];
            }
        }
        
        //01背包问题
        int idx = 0;
        for (int i = 1; i <= n; ++i) {
            if (i == p[i]) {
                sc[idx] = sc[i];
                sw[idx] = sw[i];
                idx++;
            }
        }
        
        for (int i = 0; i < idx; ++i) {
            for (int j = W; j >= sc[i]; --j) {
                f[j] = max(f[j], f[j - sc[i]] + sw[i]);
            }
        }
        
        cout << f[W] << endl;
        
        return 0;   
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    题目3237程序自动分析

    C++代码如下,

    #include 
    #include 
    #include  
    #include 
    
    using namespace std;
    
    typedef pair<int, int> PII;
    
    const int N = 200010, M = 1e9 + 10;
    int p[N];
    
    int find(int x) {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }
    
    int main() {
        int T;
        cin >> T;
        while (T--) {
            memset(p, 0, sizeof p);
            
            unordered_map<int, int> map_b_s;
    
            int n;
            cin >> n;
            
            vector<PII> equals, not_equals;
            int idx = 0;
            for (int i = 0; i < n; ++i) {
                int a, b, c;
                cin >> a >> b >> c;
                if (c == 0) {
                    not_equals.emplace_back(a,b);
                } else {
                    equals.emplace_back(a,b);
                }
                
                if (map_b_s.count(a) == 0) {
                    map_b_s[a] = idx++;
                }
                
                if (map_b_s.count(b) == 0) {
                    map_b_s[b] = idx++;
                }
            }
            
            for (int i = 0; i < idx; ++i) p[i] = i;
            
            for (auto [a, b] : equals) {
                a = map_b_s[a];
                b = map_b_s[b];
                int pa = find(a);
                int pb = find(b);
                if (pa != pb) {
                    p[pa] = pb;
                }
            }
            
            bool flag = true;
            for (auto [a, b] : not_equals) {
                a = map_b_s[a];
                b = map_b_s[b];
                int pa = find(a);
                int pb = find(b);
                if (pa == pb) {
                    flag = false;
                    cout << "NO" << endl;
                    break;
                }
            }
            if (flag) {
                cout << "YES" << endl;
            }
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    题目4239奇偶游戏

    C++代码如下,

    //带边权写法
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    const int N = 20010;
    
    int n, m;
    int p[N], d[N];
    unordered_map<int, int> S;
    
    int get(int x) {
        if (S.count(x) == 0) S[x] = ++n;
        return S[x];
    }
    
    int find(int x) {
        if (p[x] != x) {
            int root = find(p[x]);
            d[x] += d[p[x]];
            p[x] = root;
        }
        return p[x];
    }
    
    int main() {
        cin >> n >> m;
        n = 0;
        
        for (int i = 0; i < N; ++i) p[i] = i;
        
        int res = m;
        for (int i = 1; i <= m; ++i) {
            int a, b;
            string type;
            cin >> a >> b >> type;
            a = get(a - 1), b = get(b);
            
            int t = 0;
            if (type == "odd") t = 1;
            
            int pa = find(a), pb = find(b);
            if (pa == pb) {
                if (((d[a] + d[b]) % 2 + 2) % 2 != t) {
                    res = i - 1;
                    break;
                }
            } else {
                p[pa] = pb;
                d[pa] = d[a] ^ d[b] ^ t;
            }
        }
        
        cout << res << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    题目5238银河英雄传说

    C++代码如下,

    #include 
    #include 
    #include 
    
    using namespace std;
    
    const int N = 30010;
    int n;
    int p[N];
    int d[N]; //到根结点的距离
    int cnt[N];
    
    int find(int x) {
        if (p[x] != x) {
            int root = find(p[x]);
            d[x] += d[p[x]];
            p[x] = root;
        }
        return p[x];
    }
    
    int main() {
        cin >> n;
        
        for (int i = 1; i < N; ++i) {
            p[i] = i;
            cnt[i] = 1;
            d[i] = 0;
        }
        
        for (int i = 0; i < n; ++i) {
            char op;
            int a, b;
            cin >> op >> a >> b;
            int pa = find(a), pb = find(b);
            if (op == 'M') {
                if (pa != pb) {
                    d[pa] = cnt[pb];
                    cnt[pb] += cnt[pa];
                    p[pa] = pb;                
                }
            } else {
                if (pa != pb) puts("-1");
                else {
                    cout << max(abs(d[a] - d[b]) - 1, 0) << endl;
                }
            }
        }
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    3 参考

    acwing算法基础之数据结构–并查集算法

  • 相关阅读:
    11.9 表达式求值
    敏捷开发流程图Scrum
    【论文阅读笔记】NTIRE 2022 Burst Super-Resolution Challenge
    JVM运行时数据区域详解
    不买后悔的阿里云服务器租用价格表_优惠活动整理_2024新版
    测试 SAP 电商云 Spartacus UI 3.4.x 和 4.3.x 的 guest checkout 功能
    基于Python实现的糖尿病预测系统
    Spring Cloud Gateway网关两种负载均衡
    Maven的安装与配置(设置本地Maven仓库、IDEA配置Maven)
    QT和网络调试助手之间的UDP通信
  • 原文地址:https://blog.csdn.net/YMWM_/article/details/138097395