题目
在某个江湖中,相互认识的人会加入同一个门派,而互不认识的人不会加入相同的门派。若甲认识乙,且乙认识丙,那么甲和丙就算是认识的。对于给定的认识关系,请计算共有多少个门派,人数最多的门派有多少人。
输入格式
首先输入一个整数T,表示测试数据的组数,然后是T组测试数据。每组测试首先输入两个整数n、m(1≤n≤1000,1≤m≤n(n-1)/2),n表示总人数,m表示认识关系数。然后输入m行,每行两个整数A、B(1≤A,B≤1000,且A!=B),表示编号为A、B的两人互相认识。
输出格式
对于每组测试,输出门派总数和人数最多的门派拥有的人数。
输入样例
2
5 3
1 2
2 3
4 5
5 1
2 5
输出样例
2 3
4 2
思路
本题是一道并查集算法的基础题,解决此类连通块问题,就可以考虑到并查集,具体实现请看代码分析。
代码实现
#include<bits/stdc++.h>
using namespace std;
class UF{//定义类UF(并查集)
public:
vector<int>pre;//父组
vector<int>size;//门派的人数
UF(int n){
pre.resize(n);
size.resize(n,1);//初始人数为1
for(int i=0;i<n;i++){
pre[i]=i;
}//并查集初始化
}
int root(int x){
return pre[x]=(pre[x]==x?x:root(pre[x]));
}//寻找根,这里采用了路径压缩减少runtime
void merge(int x,int y){
x=root(x);
y=root(y);
if(x!=y){
pre[x]=y;
size[y]+=size[x];
}
}//将两数合并,并且将子门派的人数加入到父门派
};
int main(){
int t;
cin>>t;
while(t--){
int a,b,n,i,m,count,ren=0;
cin>>n>>m;
UF f(n);//定义对象
while(m--){
count=0;
cin>>a>>b;
f.merge(a-1,b-1);
}//数组从0开始
for(i=0;i<n;i++){
if(f.pre[i]==i){//如果pre[i]==i,说明这是门派根
count++;//记录门派根的个数
ren=max(f.size[i],ren);//更新最大人数
}
}
cout<<count<<' '<<ren<<endl;
}//输出门派和人数
}
C语言版本
#include<stdio.h>
#include<string.h>
int pre[1005],size[1005];//定义全局变量,否则新定义函数找不到
int root(int x); //调用
void merge(int x,int y); //调用
int main(){
int t;
scanf("%d",&t);
while(t--){
int a,b,n,i,m,count,ren=0;
scanf("%d%d",&n,&m);
//初始化每个人对应一个门派
for(i=0;i<n;i++){
pre[i]=i;//初始化父组,使每个门派指向自己
size[i]++;//让每个门派人数初始为1
}
while(m--){
count=0;
scanf("%d%d",&a,&b);
merge(a-1,b-1);//将两个同门派的人合并成一个门派,人数加1
}//数组从0开始,故都-1对应合并
for(i=0;i<n;i++){
if(pre[i]==i){//如果pre[i]==i,说明这是门派根
count++;//记录门派根的个数
ren=size[i]>ren?size[i]:ren;//更新最大人数
}
}
printf("%d %d\n",count,ren);
memset(size,0,sizeof size);//重新给size赋值为零,为下次使用做准备
}//输出门派和人数
}
int root(int x){
return pre[x]=(pre[x]==x?x:root(pre[x]));
}//寻找根,这里采用了路径压缩减少runtime
void merge(int x,int y){
x=root(x);
y=root(y);
if(x!=y){
pre[x]=y;
size[y]+=size[x];
}
}//将两数合并,并且将子门派的人数加入到父门派,并将子门派人数加到父门派
反思
本题采用了并查集,并使用路径压缩的解法来减少runtime是一种高效的查询方式,帮助我们顺利解决连通块问题,可以借此来学习并查集的应用和理解方式。
尾声
希望通过这道题目让大家学会使用并查集,大家多多加油哦~不要忘啦给笔者的点赞关注收藏喔~