并查集专题练习:好朋友(未完待续)
Posted CSU迦叶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并查集专题练习:好朋友(未完待续)相关的知识,希望对你有一定的参考价值。
有空再把题目补上
输入样例1
4 2
1 4
2 3
样例输出1
2
输入样例2
7 5
1 2
2 3
3 1
1 4
5 6
输出样例2
3
解题思路:
1. 这题放在并查集的专题后面,有查找也有合并,需要具备的基础只是是合并和查找的函数要会写(都很简单)。但是读到每组好朋友的关系时,应该是调用合并函数,而不是随便把一个设置为另一个的父亲orz。
2. 在读朋友关系前把所有节点的父节点都设置成自身,也就是默认为根节点,大不了之后不是再被覆盖掉。
3. 怎样统计根节点的个数呢?起初的设想是,用一个向量容器存放,对于每一个结点,先看它的源头在不在容器内,不再才加进去,最后输出向量的大小。优化方案:不用向量容器,直接用集合容器,不用判断在不在,插入所有的源节点,最后输出集合大小即可。
4. 注意合并集合的函数,是让一个根结点成为另一个的子节点,而不是参数a成为参数b的子节点。
AC代码
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<cstring>
#include<iostream>
#include<vector>
#include<stack>
#include<queue>
#include<algorithm>
#include<cmath>
typedef long long LL;
using namespace std;
const int maxn = 100;
int F[maxn];
int findSource(int x){
while(x!=F[x]){
x = F[x];
}
return x;
}
void unite(int a,int b){//将a和b所在的集合合并
int sa = findSource(a);
int sb = findSource(b);
if(sa!=sb){
F[sa] = sb;//这里特别容易写错
}
}
int main(){
int n,m,a,b;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
F[i] = i;
}
for(int i=0;i<m;i++){
scanf("%d %d",&a,&b);
unite(a,b);
}
set<int> roots;
for(int i=1;i<n;i++){
int source = findSource(i);
roots.insert(source);
}
printf("%d",roots.size());
return 0;
}
以上是关于并查集专题练习:好朋友(未完待续)的主要内容,如果未能解决你的问题,请参考以下文章
团体程序设计天梯赛-练习集 L3-003 社交集群 并查集 解题报告