当前位置: 首页 > article >正文

7-6 最小生成树-prim

目录

题目描述

输入格式:

输出格式:

输入样例:

输出样例:

解题思路:

举个例子:

详细代码:

堆优化的prim详细代码:


题目描述

题目给出一个无向连通图,要求求出其最小生成树的权值。

温馨提示:本题请使用prim最小生成树算法。

输入格式:

第一行包含两个整数 N(1<=N<=1x104),M(1<=M<=2x106) 表示该图共有 N 个结点和 M 条无向边。

接下来 M 行每行包含三个整数 Xi​,Yi​,Zi​ ,表示有一条长度为 Zi​ 的无向边连接结点 Xi​,Yi​ 。

输出格式:

输出一个整数表示最小生成树的各边的长度之和。

输入样例:

4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3

输出样例:

7

解题思路:

思想与dijkstra相同

即从1号点开始,将其纳入集合,查找与其距离最短的边,只需记录该点的终点是否走过,

然后将这条边连接的点也纳入集合中,查找与这个集合距离最短的另一条边,依次进行下去。

举个例子:

根据输入样例

4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3

可以构建一个如图所示的无向图

定义最小生成树总权值sum=0

首先将1号点放入集合中,集合{1}

查找与集合1最近的边为1到2的边权值为2,总权值sum=sum+2=2

之后2进入集合{1,2}

查找与集合最近的边为1到3的边权值为2,总权值sum=sum+2=4

之后3进入集合{1,2,3}

查找与集合最近的边为1到4的边权值为3,总权值sum=sum+3=7

构建最小生成树如下图

此时集合中有{1,2,3,4}全都被标记在集合中

详细代码:

#include <iostream>
#include <cstring>
#include <algorithm> 
#include <vector>
using namespace std;

const int N=1e5+7;
struct asd{
	int x,y;
};
vector<asd>ljb[N];
int dist[N];//当前点i到集合的最短距离
int st[N];//等于1在集合中,等于0不在集合中
int n, m;
int prim(){
	memset(dist,0x3f,sizeof dist);
	int res=0;//计算生成树最小权值
	for (int i=0;i<n;i++) {
		int t=-1;
		for (int j=1;j<=n;j++) {
			if (st[j]==0&&(t==-1||dist[t]>dist[j]))//找到当前离集合最短距离的点
				t=j;
		}
		if(i)
		{
			res+=dist[t];
		}
		st[t]=1;
		for (int j=0;j<ljb[t].size();j++) {
			asd ls=ljb[t][j];
			dist[ls.x]=min(dist[ls.x],ls.y);//更新点到集合的最短距离
		}
	}
	return res;
}
int main() {
	scanf("%d %d",&n,&m);
	while(m--){
		int a,b,c;
		scanf("%d %d %d",&a,&b,&c);;
		ljb[a].push_back({b,c});//邻接表储存边信息
		ljb[b].push_back({a,c});
	}
	int t=prim();
	printf("%d",t);
}

堆优化的prim详细代码:

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;

const int N = 1e4+10;

typedef pair<int,int> PII;//用PTT替换pair<int,int>文本

vector<PII>ljb[N]; 
bool vis[N];//记录是否走过
int dis[N];
int n,m;

void prim()
{
	memset(dis,0x3f,sizeof dis);//将其他点到集合的距离设为无穷大
	dis[1] = 0;//初始化1到集合的距离
	int res = 0;
	priority_queue<PII,vector<PII>,greater<PII>> q;//优先队列,将距离更小的放在前面
	q.push({0,1});
	
	while(!q.empty())
	{
		int t = q.top().second;//取出当前出队的点
		q.pop();
		if(vis[t]) continue;//如果走过即跳过
		vis[t] = true;//走了则标记
		res += dis[t];//记录最小生成树的权值
		for(auto ls:ljb[t])//遍历与t相邻的点的距离
		{
			int k=ls.first,w=ls.second;
			if(dis[k]>w)//如果之前更新的相邻点的与当前点的距离大于现在更新的距离则替换
			{
				dis[k]=w;
				q.push({w,k});//将距离和该点入队
			}
		}
	}
	printf("%d",res);
}

int main()
{
	scanf("%d%d",&n,&m);
	
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		
		ljb[u].push_back({v,w});//邻接表存储边信息
		ljb[v].push_back({u,w});
	}
	prim();
	return 0;
}


http://www.kler.cn/a/454658.html

相关文章:

  • Linux系统之stat命令的基本使用
  • 15、【OS】【Nuttx】OS裁剪,运行指定程序,周期打印当前任务
  • LaTeX 是一种基于标记的排版系统,广泛用于创建高质量的文档,特别是在需要复杂数学公式、表格、文献引用等的场景中
  • Spring API 接口加密/解密
  • 数据仓库和数据湖 数据仓库和数据库
  • QT-【常用容器类】-QList类 QLinkedList类
  • HTTPS验证流程
  • 地理数据库Telepg面试内容整理-在Telepg数据库中,如何进行空间数据的存储与管理
  • 基于STM32的智能家居环境监控系统设计
  • 【Linux】Centos7下载npm
  • Java(三十六)集合-List ArrayList LinkedList接口
  • java基础1:处理Map
  • 《机器学习》KNN算法实现手写数字识别
  • Dots 常用操作
  • 云手机+Facebook:让科技与娱乐完美结合
  • C++--------继承
  • 了解jvm -server和-client 参数
  • 【ETCD】【实操篇(十八)】ETCD监控实战:提升系统健康与集群调试效率
  • platform_msi使用
  • 【Git】—— 使用git操作远程仓库(gitee)
  • httpclient GET 和POST 请求
  • Qt存储大整数到`JsonValue`
  • 赋能开发者 | 麒麟信安受邀参加2024开放原子开发者大会,以技术为引领,以人才创发展
  • 解读DeepseekV3
  • Go+chromedp实现Web UI自动化测试
  • uniapp 文本转语音