曾经沧海难为水,除却巫山不是云。|

Joey-Wang

园龄:4年3个月粉丝:17关注:0

9.6 并查集

9.6 并查集

http://codeup.hustoj.com/contest.php?cid=100000615

B 畅通工程

image-20200827144711658

题目解析

第一行n、m,接下来m行为相联系的各个结点。
求将n个结点都联系在一起,还需至少几条关系。

所以只需要找到目前m条联系后,n个结点内有几个并查集ans,最后答案为ans - 1
找n个结点内有几个并查集:遍历n各结点,若i与其father[i]相等,证明这个节点的根结点就是它自己,所以ans++

注意点⚠️
1️⃣在Union之前,需要将n个结点的father初始化为自己,即father[i]=i
(for循环从1开始,不从0开始,因为输入的m个关系中结点从1开始)

代码

#include <cstdio>
#define maxn 1005
int father[maxn];
int n, m;

int findFather(int x) {
    if (x == father[x]) return x;
    else {
        int v = findFather(father[x]);
        father[x] = v;
        return v;
    }
}

void Union(int a, int b) {
    int faA = findFather(a);
    int faB = findFather(b);
    if (faA != faB) father[faA] = faB;
}

int main() {
    int a, b;
    while (scanf("%d", &n) && n) {
        scanf("%d", &m);
        for (int i = 1; i <= n; i++) father[i] = i;
        while (m--) {
            scanf("%d%d", &a, &b);
            Union(a, b);
        }
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            if (i == father[i]) ans++;
        }
        printf("%d\n", ans - 1);
    }
    return 0;
}

D More is better

image-20200827145427840

题目释义

一个房间里面有若干人maxn(0 ≤ n ≤10 000 000)。他们之间有些是朋友有些不是。现在从中选出一个群体(朋友的朋友也是朋友都是一个群体)。要使这个群体最大。

现在输入他们之间的关系:
第一行输入有多少个关系需要输入n (0 ≤ n ≤ 100 000)。
以下n行为具体的关系。
若输入1 2 。则表示1和2是朋友。

题目解析

这道题要求所有人maxn(0 ≤ n ≤10 000 000),添加n(0 ≤ n ≤ 100 000)个关系后,形成的所有并查集中最大并查集的元素个数

注意点⚠️
1️⃣ 初始化father[i]=i时,要对所有人maxn初始化,因为不知道输入的关系中最大的结点是啥
2️⃣ 求每个并查集中元素数目:设立group[maxn]数组,遍历所有结点,将group[findFather(i)]++
(❗️是findFather不是father,虽然在findFather中使用了路径压缩,让所有的father都是根结点,但最后一次Union后没有使用过findFather,所以有一些结点的father不是根结点)
3️⃣这里本来最后两个for循环也是for (int i = 1; i <= maxn; i++) ,但是这样“时间超限”,所以优化了下,设置循环截止条件为max,max是n个关系中最大的结点。
(因为最后并查集是在输入了关系的结点之间,之前因为不知道最大结点是啥,才在初始化时直接初始化所有结点)

代码

#include <cstdio>
#include <cstring>

#define maxn 10000005
int father[maxn];
int group[maxn];

int findFather(int x) {
    if (x == father[x]) return x;
    else {
        int v = findFather(father[x]);
        father[x] = v;
        return v;
    }
}

void Union(int a, int b) {
    int faA = findFather(a);
    int faB = findFather(b);
    if (faA != faB) father[faA] = faB;
}

int main() {
    int n, a, b, max, ans;
    while (scanf("%d", &n) != EOF) {
        memset(group, 0, sizeof(group));
        max = 0;
        ans = 1;
        for (int i = 1; i <= maxn; i++) father[i] = i;  //!!!是maxn
        for (int i = 1; i <= n; i++) {
            scanf("%d%d", &a, &b);
            Union(a, b);
            if (a > max) max = a;
            if (b > max) max = b;
        }
        for (int i = 1; i <= max; i++) {
            group[findFather(i)]++;  //!!!是findFather不是Father
        }
        for (int i = 1; i <= max; i++) {
            if (group[i] > ans) ans = group[i];
        }
        printf("%d\n", ans);
    }
    return 0;
}

本文作者:Joey-Wang

本文链接:https://www.cnblogs.com/joey-wang/p/14541186.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Joey-Wang  阅读(34)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开