考虑到题目需要求出人数最多的班级,也就是秩最大的班级,引入ranks数组记录,同时小挂大似乎也是一种优化,最后的班级数量再来一遍遍历,如果父节点是自身,说明它就是该集合的父节点(已经使用了路径压缩)
#include<bits/stdc++.h>
using namespace std;
int n,m,ans;
vector<int>f,ranks;
void build(){
for(int i=1;i<=n;i++){
f[i]=i;
ranks[i]=1;
}
}
int find_f(int x){
if(f[x]!=x){//如果父节点不是自己,往上一直搜直到搜到父节点等于自身的,也即集合的父节点,指向它即可,这就是路径压缩
f[x]=find_f(f[x]);
}
return f[x];
}
void union_set(int x,int y){
int f_x=find_f(x),f_y=find_f(y);
if(f[x]!=f[y]){
if(ranks[f_x]>ranks[f_y]){//小挂大
f[f_y]=f_x;
ranks[f_x]+=ranks[f_y];
ans=max(ranks[f_x],ans);
}
else{
f[f_x]=f_y;
ranks[f_y]+=ranks[f_x];
ans=max(ranks[f_y],ans);//每次比较人数
}
}
}
int main(){
cin>>n>>m;
int classes=0;
f.resize(n+1);
ranks.resize(n+1);
build();
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
union_set(u,v);//由于同一行的是同班的,直接联合
}
for(int i=1;i<=n;i++){//来个遍历统计班级数量
if(f[i]==i){
classes++;
}
}
cout<<classes<<' '<<ans<<endl;
}