并查集

大致由一个整数数组(pre[])和两个函数(join()/find())组成

int find(int x){
    if(pre[x]==x) return x;
    else{
        pre[x]=find(x);
        return pre[x];    
    }
}

int join(int x,int y){
    int a,b;
    a=find(x);
    b=find(y);
    if(a!=b) pre[a]=b; 

}

例题有 

7-8 朋友圈 (25 分) 

#include<bits/stdc++.h>
using namespace std;
int stu[300010];
int ans[300010];
/*
并查集由一个整数型数组pre[x](记录x的前导点)和两个函数(find和join)组成 
*/
int find(int x){
	if(stu[x]==x){
		return stu[x];
	}else{
		stu[x]=find(stu[x]);  //例 123 14 join(1,2) join(1,3) join(1,4) 连成1234 朋友圈里有四个人  
		return stu[x];
	}
} 
int join(int x,int y){
	int a,b;
	a=find(x);
	b=find(y);
	if(a!=b){
		stu[a]=b;
	}
}
int main(){
	int n,m;  //n学生总数 m俱乐部个数 
	int x,y,z; 
	cin>>n>>m;
	for(int i=1;i<=n;i++){ //初始化 
		stu[i]=i;
	}
	for(int i=0;i<m;i++){
		cin>>z>>x;  //俱乐部的人数和第一位学生
		for(int j=1;j<z;j++){
			cin>>y;
			join(x,y);
		} 
	}
	int max=0;  //朋友圈的最大人数
	 for(int i=1;i<=n;i++){
	 	int c = find(i); //例 i从1到4 find函数最终找到的都是4  5到7find的结果都是7 
	 	ans[c]++;   //所以ans[4]会加4次等于4  ans[7]等于3 
	 	if(max<ans[c]){
	 		max=ans[c];
		 }
	 }
	cout<<max;
/*
如果要找朋友圈的个数 判断 stu[i]==i 因为 stu[4]=4 stu[7]=7 

	int count=0;
    for(int i=1;i<=n;i++){
    	if(stu[i]==i){
    		count++;
		}
	} 
	cout<<count;
*/
	return 0;
}

7-17 社交集群 (30 分)

#include<bits/stdc++.h>
using namespace std;
//和朋友圈那题相似都使用并查集 
int people[1001]; 
int find(int x){
	if(people[x]==x){
		return people[x];
	}else{
		people[x]=find(people[x]); 
		return people[x];
	}
}
int join(int x,int y){
	int a,b;
	a=find(x);
	b=find(y);
	if(a!=b){
		people[a]=b;
	} 
}
bool cmp(int x,int y){    //从大到小排序 非增序 
	return x>y;  
} 
int main(){
	int n;
	int h[1001]={0};  //先初始化 以便后面标记 
	int ans[1001]={0};  
	int res[1001]={0};  //存储每个兴趣圈里的人数 
	char c; //冒号 
	for(int i=1;i<=1001;i++){
		people[i]=i;
	}
	cin>>n;
	for(int i=1;i<=n;i++){  //修改从1开始 因为下面有标记 
		int x;
		cin>>x>>c;
		for(int j=1;j<=x;j++){
			int y;
			cin>>y;
			if(h[y]==0){  //兴趣没被标记 
				h[y]=i; 
			}else{  //被标记过了就合并(就是一个兴趣圈超过了两个人) 
				join(h[y],i); 
			}
		}
    }
		int max=0;
		int count=0;  //开始计算兴趣圈个数 和之前的朋友圈题目差不多 
		for(int i=1;i<=n;i++){   //(查找用户)计算兴趣圈个数 
			if(people[i]==i){
				count++;
			}
			res[find(i)]++;  //记录兴趣圈人数 假如1234有关联就会自加四次 而find()的值是不变的 我理解为find()指向这条关系的终点 
		}
		sort(res,res+1001,cmp);
		cout<<count<<endl;
		int flag=0;
		for(int i=0;i<1001;i++){ 
				if(res[i]!=0){
					cout<<res[i];
					flag++;
				}
				if(flag!=count){
					cout<<" ";
				}
				if(flag==count){
					break;
				}
		}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值