首页 > 其他分享 >最小生成树

最小生成树

时间:2025-01-17 20:59:15浏览次数:1  
标签:std cnt struct int 最小 生成 using dis

最小生成树

[生成树]
从一个无向连通图中选取一些边使这张图是一颗树。
[最小生成树]
在生成树的基础上使边权和最小。 
[Kruskal]
寻找满足条件的边 
贪心,从未选取的边中选一条边权最小的边,
选完后不出环即可。
我们需要判断:
1.当前最小边权的边。 
2.这条边所连接的两个点的连通性。
用并查集判断即可。
[Prim]
寻找满足条件的点
在没有加入连通块的点中选一个最近的加入连通块,
我们需要判断:
1.哪些点还没有加入连通块
2.这些点与连通块的距离
3.距离最近的点 
eg:
1. 
accoders【一本通图 最小生成树】最短网络(agrinet)2023
luogu P1546 [USACO3.1] 最短网络 Agri-Net 
思路:
最小生成树的板子。 
[Kruskal]
code:
#include<bits/stdc++.h>
using namespace std;
int n,a[110][110];
struct node{
	int l,r,w;
	bool operator <(const node &ret)const{
		return w<ret.w;
	}
}e[1000010];
int cnt,fa[1000100],ans=0,tot=0;
int find(int x){
	if(fa[x]==x){
		return x;
	}
	return fa[x]=find(fa[x]);
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>a[i][j];
			if(i<j){
				e[++cnt]={i,j,a[i][j]};
			}
		}
	}
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
	sort(e+1,e+cnt+1);
	for(int i=1;i<=cnt;i++){
		int l=e[i].l,r=e[i].r,w=e[i].w;
		int fl=find(l),fr=find(r);
		if(fl!=fr){
			fa[fl]=fr;
			tot++;
			ans+=w;
		}
		if(tot==n-1){
			break;
		}
	}
	cout<<ans;
	return 0;
}
2.
accoders的【一本通图 最小生成树】 局域网
luogu P2820 局域网
思路:
求出最小生成树后用边权总和减去最小生成树的边权和即可。 
[Prim]
code:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
const int N=100010;
struct node{
	int to,l;
};
int n,m,ans,tot;
vector<node>mp[N+10];
int vis[N+10],dis[N+10];
void prim(int rt){
	priority_queue<P,vector<P>,greater<P> >q;
	dis[rt]=0;
	q.push(P(dis[rt],rt));
	while(!q.empty()){
		int l=q.top().second,w=q.top().first;
		q.pop();
		if(vis[l]){
			continue;
		}
		vis[l]=1;
		ans+=w;
		for(auto v:mp[l]){
			if(dis[v.to]>v.l){
				dis[v.to]=v.l;
				q.push(P(dis[v.to],v.to));
			}
		}
	}
} 
int main(){
	cin>>n>>m;
	memset(dis,0x3f3f3f3f,sizeof dis);
	for(int i=1;i<=m;i++){
		int l,r,w;
		cin>>l>>r>>w;
		mp[l].push_back({r,w});
		mp[r].push_back({l,w});
		tot+=w;
	}
	prim(1);
	cout<<tot-ans;
	return 0;
}
[Kruskal]
#include<bits/stdc++.h>
using namespace std;
int n,k,cnt;
struct node{
	int l,r,w;
	bool operator <(const node &W)const{
		return w<W.w;
	}
}mp[110*110];
int fa[110*110];
int find(int x){
	if(fa[x]==x){
		return x;
	}
	return fa[x]=find(fa[x]);
}
int main(){
	cin>>n>>k;
	int tot=0,ans=0;
	for(int i=1;i<=k;i++){
		int l,r,w;
		cin>>l>>r>>w;
		mp[++cnt]={l,r,w};
		tot+=w;
	}
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
	sort(mp+1,mp+cnt+1);
	for(int i=1;i<=cnt;i++){
		int l=mp[i].l,r=mp[i].r,w=mp[i].w;
		int fl=find(l),fr=find(r);
		if(fl!=fr){
			fa[fl]=fr;
			ans+=w;
		}
	}
	cout<<tot-ans;
	return 0;
}

3.
accoders的【一本通图 最小生成树】 繁忙的都市 2025
luogu P2330 [SCOI2005] 繁忙的都市
思路:
最小生成树但是要求有多少个边和边权最大的边。 
code:
[Kruskal]
#include<bits/stdc++.h>
using namespace std;
int n,m,cnt,tot,ma=-1;
struct node{
	int l,r,w;
	bool operator <(const node &W)const{
		return w<W.w;
	}
}mp[310*310];
int fa[310*310];
int find(int x){
	if(x==fa[x]){
		return x;
	}
	return fa[x]=find(fa[x]);
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int l,r,w;
		cin>>l>>r>>w;
		mp[++cnt]={l,r,w};
	}
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
	sort(mp+1,mp+cnt+1);
	for(int i=1;i<=cnt;i++){
		int l=mp[i].l,r=mp[i].r,w=mp[i].w;
		int fl=find(l),fr=find(r);
		if(fl!=fr){
			fa[fl]=fr;
			tot++;
			ma=max(ma,w); 
		}
	}
	cout<<tot<<" "<<ma;
	return 0;
}
4.
accoders的【一本通图 最小生成树】联络员(liaison)2026
思路:
先将必选选入,然后从小到大做非必选的最小生成树即可。 
code:
[Kruskal]
#include<bits/stdc++.h>
using namespace std;
int fa[2001*2001],cnt;
struct node{
	int l,r,w,fl;
	bool operator <(const node &W)const{
		return w<W.w;
	}
}mp[2001*2001];
int find(int x){
	if(x==fa[x]){
		return x;
	}
	return fa[x]=find(fa[x]);
}
int main(){
	int n,m;
	cin>>n>>m;
	int tot=0,ans=0;
	for(int i=1;i<=m;i++){
		int l,r,w,f;
		cin>>f>>l>>r>>w;
		mp[++cnt]={l,r,w,f};
	}
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
	sort(mp+1,mp+cnt+1);
	for(int i=1;i<=cnt;i++){
		int l=mp[i].l,r=mp[i].r,w=mp[i].w,f=mp[i].fl;
		int fl=find(l),fr=find(r);
		if(f==1){
			fa[fl]=fr;
			ans+=w;
			tot++;
		}
	}
	for(int i=1;i<=cnt;i++){
		int l=mp[i].l,r=mp[i].r,w=mp[i].w,f=mp[i].fl;
		int fl=find(l),fr=find(r);
		if(fl!=fr&&f==2){
			fa[fl]=fr;
			ans+=w;
			tot++;
		}
	}
	cout<<ans;
	return 0;
}
5.
accoders 的【一本通图 最小生成树】 连接格点2098
思路:
通过类似hash的操作将格点强行建边,
把给的边放入边数组中,然后跑一遍最小生成树。 
code(感谢little_sheep_2024的code):
#include<bits/stdc++.h>
using namespace std;
int m,n,f[1000005];
int x,xx,y,yy,idx=0;
struct edge{
	int u,v,w;
}e[5000005];

int find(int u){
	return f[u]==u ? u : f[u]=find(f[u]);
}

int fe(int x,int y){
	return m*(x-1)+y;
}

bool cmp(edge x,edge y){
	return x.w<y.w;
}

int kruscal(){
	int ans=0;
	sort(e+1,e+idx+1,cmp);
	for(int i=1;i<=idx;i++){
		int fu=find(e[i].u);
		int fv=find(e[i].v);
		if(fu!=fv){
			ans+=e[i].w;
			f[fu]=fv;
		}
	}
	return ans;
}

int main(){
	cin>>n>>m;
	for(int i=1;i<=n*m;i++){
		f[i]=i;
	}
	while(cin>>x>>y>>xx>>yy){
		int fu=find(fe(x,y));
		int fv=find(fe(xx,yy));
		f[fu]=fv;
	}
	for(int i=1;i<m;i++){
		for(int j=1;j<=n;j++){
			e[++idx].u=fe(j,i),e[idx].v=fe(j,i+1);
			e[idx].w=2;
		}
	}
	for(int i=1;i<n;i++){
		for(int j=1;j<=m;j++){
			e[++idx].u=fe(i,j),e[idx].v=fe(i+1,j);
			e[idx].w=1;
		}
	}
	cout<<kruscal();
	return 0;
} 
 
6.
accoders的【一本通提高篇最小生成树】新的开始2098
思路:
将建设发电机的费用变成一个点放在原本的图外,
这样建设发电机就变成了连一个费用为V的边,
然后就成了一个大图的最小生成树。 
code:
[Kruskal]
#include<bits/stdc++.h>
using namespace std;
const int N=1000010;
int n;
struct node{
	int l,r,w;
	bool operator <(const node &W) const{
		return w<W.w;
	}
}mp[N];
int cnt,fa[N];
int find(int x){
	if(fa[x]==x){
		return x;
	}
	return fa[x]=find(fa[x]);
}
int main(){
	cin>>n;
	for(int i=1;i<=n+1;i++){
		fa[i]=i;
	}
	for(int i=1;i<=n;i++){
		int v;
		cin>>v;
		mp[++cnt]={i,n+1,v};
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			int w;
			cin>>w;
			if(i<j){
				mp[++cnt]={i,j,w};
			}
		}
	}
	sort(mp+1,mp+cnt+1);
	int tot=0,ans=0;
	for(int i=1;i<=cnt;i++){
		int l=mp[i].l,r=mp[i].r,w=mp[i].w;
		int fl=find(l),fr=find(r);
		if(fl!=fr){
			fa[fl]=fr;
			ans+=w;
			tot++;
		}
		if(tot>=n){
			break;
		}
	}
	cout<<ans;
	return 0;
}
 

标签:std,cnt,struct,int,最小,生成,using,dis
From: https://www.cnblogs.com/123lbh321/p/18677654

相关文章

  • 重构经历_编写代码生成器
    我的重构经历:编写代码生成器概述背景多年前,我开发了一个基于C#的Windows程序——代码生成器,并在此后十多年间持续优化。该程序能够根据数据库表结构生成代码,并将结果显示在文本框中。最初是从同事那里接手的一个简单项目,经过不断扩展和重构,最终实现了通过数据库自动生成具备完......
  • 编程题-最小高度树
    题目:给定一个有序整数数组,元素各不相同且按升序排列,编写一个算法,创建一棵高度最小的二叉搜索树。解法一(二分查找+二叉搜索树构建):二叉搜索树的中序遍历是升序序列,题目给定的数组是按照升序排列的有序数组,因此可以确保数组是二叉搜索树的中序遍历序列。二叉搜索树中,左子树的......
  • MiniMax TTS新模型T2A-01-HD:情感控制10秒克隆限时免费;真人表演+文本命令,Kinetix精准生
      开发者朋友们大家好: 这里是**「RTE开发者日报」**,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享RTE(Real-TimeEngagement)领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,但内容仅代表编......
  • 网站目录中的PHP脚本无法写入,导致缓存文件生成失败
    根据您的描述,您遇到了网站目录中的PHP脚本无法写入的问题,这直接影响了缓存文件的生成,进而导致网站运行不正常。具体来说,espcms_datacache/_templates 和 espcms_datacache/dbcache 目录下的PHP文件无法写入,这对网站性能和功能产生了负面影响。要解决这个问题,您可以按照以下步......
  • 【无人机】基于一组配备图像传感器的无人驾驶飞行器(UAV)对地面区域进行最小时间覆盖问
     ......
  • Java生成10位随机数的方法
    在Java中生成10位随机数有多种方法,以下是一些常见的实现方式:方法一:使用Random类java复制importjava.util.Random;publicclassRandomNumberGenerator{publicstaticvoidmain(String[]args){Randomrandom=newRandom();longrandomNumber......
  • 28、【OS】【Nuttx】最小系统初始化分析(4):定时器(二)
    背景接上篇wiki27、【OS】【Nuttx】最小系统初始化分析(4):定时器(一)分析了定时器初始化过程,以及初始化生成的定时器实例,并着重分析了实例对象里的sim_current方法,接下来对最小系统中,定时器的启动,以及执行的任务进行分析定时器启动来看定时器启动函数sim_start,这里有两......
  • 谷歌60s视频生成模型Veo的技术亮点
    谷歌60s视频生成模型Veo的技术亮点如下:高分辨率长视频生成高分辨率输出:能够生成高质量的1080p分辨率视频,可满足长视频内容制作需求,如用于电影、广告等对画质要求较高的场景。时长优势:能创建超过60秒的视频,可将一系列提示拼接在一起讲述完整故事,在长内容创作上更具优势。多......
  • 生成函数
    生成函数浅讲感觉这是一个非常牛逼的东西,写了点自己的感悟,可能讲得不是很清楚。生成函数的定义就比较牛,将数列\(\{a_i\}\)写成一个函数\(A(x)=\sum{a_ix^i}\)的形式叫做普通生成函数。此处的\(x^i\)没有实际意义,只是一个占位符。对于生成函数来说,绝大数多项式的运算法则......
  • 代码随想录:二叉搜索树的最小绝对值
    遍历二叉搜索树,定义一个全局的上一个节点确实好用/***Definitionforabinarytreenode.*structTreeNode{*intval;*TreeNode*left;*TreeNode*right;*TreeNode():val(0),left(nullptr),right(nullptr){}*TreeNode(intx):......