9.6 并查集
9.6 并查集
http://codeup.hustoj.com/contest.php?cid=100000615
B 畅通工程

题目解析
第一行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

题目释义
一个房间里面有若干人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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步