ACM:并查集专题


注意:
        1、专题系列难度随机。由于有些OJ网站不易被打开,无法查看原题目,所以所有的题目链接都指向VJ(Virtual Judge)中对应的题目。VJ中有题目的原出处,需要的自取!
        2、为了让大家更易于理解AC码,每一道题的代码风格都用AI进行了优化。


A、Rumor(CodeForces 893C)

题目链接:Rumor(CodeForces 893C)

标签:并查集

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"

int pre[100005], a[100005];

int find(int x) {
    return x == pre[x] ? x : pre[x] = find(pre[x]);
}

void join(int x, int y) {
    int fx = find(x), fy = find(y);
    if (a[fx] > a[fy]) {
        pre[fx] = fy;
    } else {
        pre[fy] = fx;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n, m;
    cin >> n >> m;

    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        pre[i] = i;
    }

    int x, y;
    while (m--) {
        cin >> x >> y;
        join(x, y);
    }

    long long sum = 0;
    for (int i = 1; i <= n; ++i) {
        if (pre[i] == i) {
            sum += a[i];
        }
    }

    cout << sum;
    return 0;
}

B、 Learning Languages(CodeForces 277A)

题目链接:Learning Languages(CodeForces 277A)

标签:并查集

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"

int pre[105], flag = 0;

int find(int x) {
    return x == pre[x] ? x : pre[x] = find(pre[x]);
}

void join(int x, int y) {
    int fx = find(x), fy = find(y);
    if (fx != fy) {
        pre[fx] = fy;
        flag = 1;
    }
}

int main() {
    int n, m, ans = 0;
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n + m; ++i) {
        pre[i] = i;
    }

    for (int i = 1; i <= n; ++i) {
        int k;
        scanf("%d", &k);
        for (int j = k; j; --j) {
            int x;
            scanf("%d", &x);
            join(x + n, i);
        }
    }

    for (int i = 1; i <= n; ++i) {
        if (pre[i] == i) {
            ans++;
        }
    }

    if (flag == 0) {
        ans++;
    }

    printf("%d", ans - 1);
    return 0;
}

C、 畅通工程(HDU 1232)

题目链接:畅通工程(HDU 1232)

标签:并查集

AC码:

#include <iostream>
using namespace std;
#define endl "\n"

int pre[1005];

int find(int x) {
    return x == pre[x] ? x : pre[x] = find(pre[x]);
}

void join(int x, int y) {
    int fx = find(x), fy = find(y);
    if (fx != fy) {
        pre[fx] = fy;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n, m;
    while (cin >> n && n != 0) {
        cin >> m;
        for (int i = 1; i <= n; ++i) {
            pre[i] = i;
        }
        while (m--) {
            int x, y;
            cin >> x >> y;
            join(x, y);
        }
        int cnt = 0;
        for (int i = 1; i <= n; ++i) {
            if (pre[i] == i) {
                cnt++;
            }
        }
        cout << cnt - 1 << endl;
    }
    return 0;
}

D、小希的迷宫(HDU 1272)

题目链接:小希的迷宫(HDU 1272)

标签:并查集

AC码:

#include <iostream>
using namespace std;
#define endl "\n"

int pre[100005], sign[100005];
int m, n, x, y, flag;

int find(int x) {
    return x == pre[x] ? x : pre[x] = find(pre[x]);
}

void join(int x, int y) {
    int fx = find(x), fy = find(y);
    if (fx != fy) {
        pre[fx] = fy;
    } else {
        flag = 0;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    while (cin >> m >> n && (m != -1 && n != -1)) {
        if (m == 0 && n == 0) {
            cout << "Yes" << endl;
            continue;
        }

        for (int i = 1; i < 100005; ++i) {
            pre[i] = i;
            sign[i] = 0;
        }

        sign[m] = sign[n] = 1;
        flag = 1;
        join(m, n);

        while (cin >> x >> y && (x != 0 && y != 0)) {
            join(x, y);
            sign[x] = sign[y] = 1;
        }

        int k = 0;
        for (int i = 1; i <= 100005; ++i) {
            if (sign[i] && pre[i] == i) {
                k++;
            }
            if (k > 1) {
                flag = 0;
            }
        }

        if (flag) {
            cout << "Yes" << endl;
        } else {
            cout << "No" << endl;
        }
    }
    return 0;
}

E、How Many Tables(HDU 1213)

题目链接:How Many Tables(HDU 1213)

标签:并查集

AC码:

#include <iostream>
using namespace std;
#define endl "\n"

int pre[1005];

int find(int x) {
    return x == pre[x] ? x : pre[x] = find(pre[x]);
}

void join(int x, int y) {
    int fx = find(x), fy = find(y);
    if (fx != fy) {
        pre[fx] = fy;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int t;
    cin >> t;

    while (t--) {
        int n, m;
        cin >> n >> m;

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

        while (m--) {
            int x, y;
            cin >> x >> y;
            join(x, y);
        }

        int cnt = 0;
        for (int i = 1; i <= n; ++i) {
            if (pre[i] == i) {
                cnt++;
            }
        }

        cout << cnt << endl;
    }

    return 0;
}

F、

题目链接:

标签:带权并查集

AC码:

在这里插入代码片

G、搭配购买(洛谷 P1455)

题目链接:搭配购买(洛谷 P1455)

标签:并查集+01背包

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"

const int MAXN = 100005;
int pre[MAXN];
int q[MAXN], v[MAXN];
int dp[MAXN];
int n, m, w;

int find(int x) {
    return x == pre[x] ? x : pre[x] = find(pre[x]);
}

void join(int x, int y) {
    int fx = find(x), fy = find(y);
    if (fx != fy) {
        q[fy] += q[fx];
        v[fy] += v[fx];
        pre[fx] = fy;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> m >> w;

    for (int i = 1; i <= n; ++i) {
        cin >> q[i] >> v[i];
        pre[i] = i;
    }

    int x, y;
    while (m--) {
        cin >> x >> y;
        join(x, y);
    }

    for (int i = 1; i <= n; ++i) {
        if (pre[i] == i) {
            for (int j = w; j >= q[i]; --j) {
                dp[j] = max(dp[j], dp[j - q[i]] + v[i]);
            }
        }
    }

    cout << dp[w] << endl;

    return 0;
}

H、

题目链接:

标签:带权并查集

AC码:

在这里插入代码片

I、修复公路(洛谷 P1111)

题目链接:修复公路(洛谷 P1111)

标签:并查集

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"

int pre[1005];

struct road {
    int x, y, t;
};

bool cmp(road a1, road a2) {
    return a1.t < a2.t;
}

int find(int x) {
    return x == pre[x] ? x : pre[x] = find(pre[x]);
}

void join(int x, int y) {
    int fx = find(x), fy = find(y);
    if (fx != fy) {
        pre[fx] = fy;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n, m;
    cin >> n >> m;

    road a[m + 1];

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

    for (int i = 1; i <= m; ++i) {
        cin >> a[i].x >> a[i].y >> a[i].t;
    }

    sort(a + 1, a + m + 1, cmp);

    for (int i = 1; i <= m; ++i) {
        int cnt = 0;
        join(a[i].x, a[i].y);
        for (int j = 1; j <= n; ++j) {
            if (j == pre[j]) {
                cnt++;
            }
        }
        if (cnt == 1) {
            cout << a[i].t;
            return 0;
        }
    }

    cout << -1;
    return 0;
}

J、家谱(洛谷 P2814)

题目链接:家谱(洛谷 P2814)

标签:并查集

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"

map<string, string> pre;

string find(string x) {
    return x == pre[x] ? x : pre[x] = find(pre[x]);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    string name, fa;
    char ch;

    cin >> ch;
    while (ch != '$') {
        cin >> name;
        if (ch == '#') {
            fa = name;
            if (pre[name] == "") {
                pre[name] = name;
            }
        } else if (ch == '+') {
            pre[name] = fa;
        } else {
            cout << name << " " << find(name) << endl;
        }
        cin >> ch;
    }

    return 0;
}

结语

我只是一个A C M预习时长两年半的蒟蒻练习生,喜欢暴力,打表,面向样例编程,请各位键盘侠手下留情。
两年半

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-George-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值