2024.7.20学习笔记

目录

并查集

1.最多单位

2.建设最少条道路

3.MST


并查集

1.最多单位

/*在某个城市里住着n个人,现在给定关于这n个人
的m条信息(每条信息格式A B,表示A和B认识)。
假设所有认识的人一定属于同一个单位,请计算
该城市最多有多少个单位*/
#include<bits/stdc++.h>
using namespace std;
#define MAX 1001
int a[MAX];
int _find(int x){ //一般查找:时间复杂度为O(n) 
	int y=x;
	while(a[y]!=x)
	y=a[y];
	return y;
}
int LJ_find(int x){//路径压缩查找:时间复杂度为O(log(n)) 
	if(a[x]!=x)
	a[x]=LJ_find(a[x]);
	return a[x];
}
void _merge(int x,int y){//将两集合合并时间复杂度为O(1) 
	int n,m;
	n=LJ_find(x),m=LJ_find(y);
	if(n!=m) a[n]=m;
}
int main(){
	int n,m,x,y;
	cin>>n>>m;
	for(int i=1;i<=n;i++)//初始化赋值(自己单独是一个集合)
	a[i]=i;
	while(m--){//进行m条信息识别 
		cin>>x>>y;
		_merge(x,y);//函数调用:合并集合 
	} 
	int maxn=0;
	for(int i=1;i<=n;i++){
		if(a[i]==i) maxn++;//统计集合个数 
	}
	cout<<"该城市最多有:"<<maxn<<endl;
	return 0;
} 

2.建设最少条道路

/*某省调查城镇交通状况,得到现有城镇道路统计表,表
中列出了每条道路直接连通的城镇。省政府“畅通工程”
的目标是使全省任何两个城镇间都可以实现交通(但不
一定有直接的道路相连,只要相互间接通过道路可达即
可)。问最少需要建设多少条道路? */
#include<bits/stdc++.h> 
using namespace std;
#define MAX 1001
int a[MAX];
int LJ_find(int x){
	if(a[x]!=x)
	a[x]=LJ_find(a[x]);
	return a[x];
}
void _merge(int x,int y){
	if(LJ_find(x)!=LJ_find(y))
	a[LJ_find(x)]=LJ_find(y);
}
void _slove(){
	int n,m,x,y;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	a[i]=i;
	while(m--){
		cin>>x>>y;
		_merge(x,y);
	}
	int maxn;
	for(int i=1;i<=n;i++)
	if(a[i]==i) maxn++;
	cout<<"最少需建设"<<maxn-1<<"条道路"<<endl; 
}
int main(){
	_slove();
	return 0;
}

3.MST

/*地图上有n个城市,现在想给这n个城市之间造路,希望能
让城市之间两两可达。给出了m种供选择的道路,每种选择 
一个三元组(u,v,w),代表给u个城市和v个城市之间建造一
条长度w的路。希望最终的道路总长越小越好(成本低)。*/
#include<bits/stdc++.h>
using namespace std;
#define MAX 1001
int fa[MAX];
struct ALu{
	int u,v,w;//u,v为城市,w为这两城市之间的道路长度 
}a[MAX];
bool _sort(ALu x,ALu y){
	return x.w<y.w;//w长度小的放前 
} 
void CSH(int n){//初始化赋值 
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
}
int fa_find(int x){
	if(fa[x]!=x) fa[x]=fa_find(fa[x]);//压缩路径 
	return fa[x];
}
int _kruskal(int l,int r){
	int sum=0;//统计最小生成数的权值
	int edge=0;//统计边的条数
	for(int i=0;i<r;i++){
		int xl=fa_find(a[i].u);
		int yr=fa_find(a[i].v);
		if(xl!=yr){
			fa[xl]=yr;//合并集合 
			sum+=a[i].w;//统计最短道路 
			edge++;//边数+1 
			if(l==edge+1) break;//顶点数=边数+1 
		} 
	}
	if(edge+1!=l) return -1; 
	else return sum; 
}
void _slove(){
	int n,m;
	cin>>n>>m;
	CSH(n);
	for(int i=0;i<m;i++)
	cin>>a[i].u>>a[i].v>>a[i].w;
	sort(a,a+m,_sort);
	cout<<_kruskal(n,m)<<endl;
}
int main(){
	_slove();
	system("pause");
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值