图论——最小生成树(Prim算法,Kruskal算法及常用模板)_prim算法和kruskal算法实现最小生成树图解-程序员宅基地

技术标签: 算法  图论  数据结构  

最小生成树算法——Prim 算法(普⾥姆)

从某⼀个顶点开始构建⽣成树;每次将代价最⼩的新顶点纳⼊⽣成树,直到所有顶点都纳⼊为⽌。

算法描述:

  1. 在一个加权连通图中,顶点集合C,边集合为E
  2. 任意选出一个点作为初始顶点,标记为,计算所有与之相连接的点的距离,选择距离最短的,标记.
  3. 重复以下操作,直到所有点都被标记为:
    在剩下的点中,计算与已标记点距离最小的点,标记,证明加入了最小生成树。

Prim算法流程图
最小生成树构造过程如下图:
Prim算法流程图

最小生成树生成的树可能不同,但是最小的权值肯定是一样的并且是最小的。
通过上小两个图可以看出图不同但是权值相同,权值相同都是15;

另一种构造方式如下图
Prim算法流程图
时间复杂度:O(n^2) 适合⽤于边稠密图

Prim代码模板

int  prim(int  k){
    //从顶点k开始构建最小生成树 
	memset(book,0,sizeof(book));//初始化标记数组 
	count=0;//初始化已经标记的点个数 
	sum=0;//初始化权重
	for(i=1;i<=n;i++){
    //初始化所有顶点
		dis[i]=e[k][i];//其余顶点与顶点k的最小距离 
	}
	book[1]=1;//标记k点 
	count++;//更新点个数
	while(count<n){
    //循环遍历各个点 
		min=inf;
		for(i=1;i<=n;i++){
    //遍历所有点
			if(book[i]==0&&dis[i]<min){
    //找到离树的最小权重并且没有被标记的点 
				min=dis[i]; 
				j=i;//找到离树的最小权重的下标 
			}
		}
		book[j]=1;//标记当前点 
		count++;更新点个数
		sum+=dis[j];加上权重
		for(k=1;k<=n;k++){
    //遍历所有点更新到树的最小权重
			if(book[k]==0&&dis[k]>e[j][k]){
    //若有更小的权重
				dis[k]=e[j][k];//更新dis 
			}	
	}
	return  sum; 
}

例题 POJ - 1258 Agri-Net

传送门
Farmer John has been elected mayor of his town! One of his campaign promises was to bring internet connectivity to all farms in the area. He needs your help, of course.
Farmer John ordered a high speed connection for his farm and is going to share his connectivity with the other farmers. To minimize cost, he wants to lay the minimum amount of optical fiber to connect his farm to all the other farms.
Given a list of how much fiber it takes to connect each pair of farms, you must find the minimum amount of fiber needed to connect them all together. Each farm must connect to some other farm such that a packet can flow from any one farm to any other farm.
The distance between any two farms will not exceed 100,000.
Input
The input includes several cases. For each case, the first line contains the number of farms, N (3 <= N <= 100). The following lines contain the N x N conectivity matrix, where each element shows the distance from on farm to another. Logically, they are N lines of N space-separated integers. Physically, they are limited in length to 80 characters, so some lines continue onto others. Of course, the diagonal will be 0, since the distance from farm i to itself is not interesting for this problem.
Output
For each case, output a single integer length that is the sum of the minimum length of fiber required to connect the entire set of farms.
Sample Input
4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0
Sample Output
28
题意描述:
N个农场,要通过光纤互相连接,求最小成本。N*N代表成本情况,如21代表1->4花费21,17代表2->4花费17.。。。
解题思路:
最小生成树模板题

AC代码

#include<iostream>
#include <string.h>
int n,m,i,j,min,k,t;
int e[1005][1005],dis[10005],book[100000];
int inf=99999999;
int count=0,sum=0;
void  prim(){
    
	memset(book,0,sizeof(book));
	count=0,sum=0;
	for(i=1;i<=n;i++){
    
		dis[i]=e[1][i];
	}
	book[1]=1;
	count++;
	while(count<n){
    
		min=inf;
		for(i=1;i<=n;i++){
    
			if(book[i]==0&&dis[i]<min){
    
				min=dis[i];
				j=i;
			}
			
		}
		book[j]=1;
		count++;
		sum+=dis[j];
		for(k=1;k<=n;k++){
    
			if(book[k]==0&&dis[k]>e[j][k])
				dis[k]=e[j][k];
			}	
	}
}
int main(){
    

	while(scanf("%d",&n)!=EOF){
    
		for(i=1;i<=n;i++){
    
		for(j=1;j<=n;j++){
    
			e[i][j]=inf;
		}
	}
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++){
    
			scanf("%d",&e[i][j]); 
		} 
	prim();
	printf("%d\n",sum);
	}
	return 0;
 } 

最小生成树算法——Kruskal 算法(克鲁斯卡尔)

每次选择⼀条权值最⼩的边,使这 条边的两头连通(原本已经连通的就不选)
直到所有结点都连通

算法基本思想:

Kruakal算法的基本思想是每次都选取不会形成环的权值最小的边,但与Prim不同的是,Kruskal算法引入了连通分量来判断是否形成环。所以难点在于如何判断两个顶点是否属于同一连通分量。我们可以用并查集的思想,直接将同一连通分量的两个顶点的根 father[] 连在一起。也就是说当新的一条边加入时,判断它的两个顶点是否属于一个连通分量,即判断他们的根father[]是否相同。

遍历排序好的边集V进行如下选取,直到选取边数为n-1时

步骤1:选取未选取过的权值最小的边E(i, j)
步骤2:如果顶点i和j位于两个不同的连通分量,则选取边E(i,j)加入边集S,同时将边(i, j)的连通分量连在在一起。
步骤3:继续执行步骤12,直到选取边数为n-1时生成最小生成树

Kruskal算法流程图

时间复杂度:O( |E|log2|E| ) 适合⽤于边稀疏图

Kruskal代码模板

int Kruskal()
{
    	    
        sort(t+1, t+m+1,cmp);//排序
        for(遍历所有顶点) S[i]=i;//并查集初始化自身为一个集合 
        int total=0;//所选取的边数 
        int sum=0;//权重和 
        for(遍历排序后的所有边){
    
        	if(total==n-1) break; //直到选取了n-1条边后跳出循环 
            int x=edge[i].u,y=edge[i].v;
            if(find(x)!=find(y)){
    //若不是同一集合也就是判断是否有环
                sum+=edge[i].w;//选取这条边
                merge(x,y);//加入同一集合 
                total++;
            }
        }
        return sum;//返回权重和 
}

例题 POJ - 1287 Networking

传送门
You are assigned to design network connections between certain points in a wide area. You are given a set of points in the area, and a set of possible routes for the cables that may connect pairs of points. For each possible route between two points, you are given the length of the cable that is needed to connect the points over that route. Note that there may exist many possible routes between two given points. It is assumed that the given possible routes connect (directly or indirectly) each two points in the area.
Your task is to design the network for the area, so that there is a connection (direct or indirect) between every two points (i.e., all the points are interconnected, but not necessarily by a direct cable), and that the total length of the used cable is minimal.
Input
The input file consists of a number of data sets. Each data set defines one required network. The first line of the set contains two integers: the first defines the number P of the given points, and the second the number R of given routes between the points. The following R lines define the given routes between the points, each giving three integer numbers: the first two numbers identify the points, and the third gives the length of the route. The numbers are separated with white spaces. A data set giving only one number P=0 denotes the end of the input. The data sets are separated with an empty line.
The maximal number of points is 50. The maximal length of a given route is 100. The number of possible routes is unlimited. The nodes are identified with integers between 1 and P (inclusive). The routes between two points i and j may be given as i j or as j i.
Output
For each data set, print one number on a separate line that gives the total length of the cable used for the entire designed network.
Sample Input
1 0

2 3
1 2 37
2 1 17
1 2 68

3 7
1 2 19
2 3 11
3 1 7
1 3 5
2 3 89
3 1 91
1 2 32

5 7
1 2 5
2 3 7
2 4 8
4 5 11
3 5 10
1 5 6
4 2 12

0
Sample Output
0
17
16
26
题意描述:
题意 :给定两个点及其边权值,求出各点权值和最小的值(即生成最小生成树)

解题方法:最小生成树

这道题是一棵裸的最小二叉树,即克鲁斯卡尔算法(kruskal),算法大概内容是,首先对所有的边权值进行排序,并判断两个顶点是否连通,判断方法可借鉴并查集思想,将所有的点放入并查集中,判断两个顶点是否连通,即判断顶点是否属于一个集合内,以提升算法效率。可以用邻接矩阵存储边权值,不过在相同点之间存在多个权值时,需要取最小的权。

AC代码

#include<iostream>
#include <algorithm>
using namespace std;
struct  edge
{
    
	int u;
	int v;
	int w;
};
struct edge e[1000010],t;
int n,m;
int f[100010]={
    0},sum=0,count=0;
//sort排序cmp 
bool cmp(edge a,edge b)
{
    
	return a.w<b.w;
}
//并查集 
int getf(int v)
{
    
	if(f[v]==v)
	{
    
		return v;

	}
	else
	{
    
		f[v]=getf(f[v]);
		return f[v]; 
	} 
}
int merge(int v,int u)
{
    
	int t1,t2;
	t1=getf(v);
	t2=getf(u);
	if(t1!=t2)
	{
    
		f[t2]=t1;
		return 1;
	}
	return 0;
}
int main()
{
    
	int i;
	while(scanf("%d %d",&n,&m)&&n!=0)
	{
    
		int sum=0,count=0;
		for(i=1;i<=m;i++)
	{
    
		scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].w);
	}
	sort(e+1,e+m+1,cmp); 
	
	//Kruskal算法
	for(i=1;i<=n;i++)
	{
    
		f[i]=i;
	}
	for(i=1;i<=m;i++)
	{
    
		if(merge(e[i].u,e[i].v))//并查集判断是否有环 
		{
    
			count++;
			sum+=e[i].w;
		}
		if(count==n-1)
			break;
	}
	printf("%d\n",sum); 
	}
	
	return 0;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_46703995/article/details/119114115

智能推荐

project2016调配资源冲突-程序员宅基地

文章浏览阅读5.4k次,点赞9次,收藏26次。(1) Project查看资源负荷情况的方法和结果在工时类资源会存在资源过度分配(在同一个时间段给工时类资源分配的资源超出了他的最大单位)的情况,而成本类、材料类资源则不会有、查看资源负荷的方法有:在视图栏------资源图表如下图在这里我们可以看到每个资源的分配状况,如下图滚动鼠标滑轮就会出现不同的资源分配状况此时选择“资源”—“下一个资源过度分配处”如下图总结:甘特图、..._project2016调配资源冲突

推荐算法知识图谱模型(二):KGCN-程序员宅基地

文章浏览阅读235次。常用的KGE方法侧重于建模严格的语义相关性(例如,TransE和TransR假设头+关系=尾),这更适合于KG补全和链接预测等图内应用,而不是推荐。更自然、更直观的方法是直接设计一个图算法来利用KG结构。_图谱模型

ajax跨域与cookie跨域_一级域名 的cookie ajax 请求二级域名时获取cookie-程序员宅基地

文章浏览阅读389次。ajax跨域ajax跨域取数据(利用可以跨域加载js的原理 functioncallback(){ }这是需要返回这样一个js函数)ajax数据类型使用jsonp :如 ajax{ url:..._一级域名 的cookie ajax 请求二级域名时获取cookie

Flutter从0到1实现高性能、多功能的富文本编辑器(基础实战篇)_flutter 富文本-程序员宅基地

文章浏览阅读1.3k次,点赞2次,收藏2次。在上一章中,我们分析了一个富文本编辑器需要有哪些模块组成。在本文中,让我们从零开始,去实现自定义的富文本编辑器。注:本文篇幅较长,从失败的方案开始分析再到成功实现自定义富文本编辑器,真正的从0到1。— 完整代码太多, 文章只分析核心代码,需要源码请到代码仓库作为基础的富文本编辑器实现,我们需要专注于简单且重要的部分,所以目前只需定义标题、文本对齐、文本粗体、文本斜体、下划线、文本删除线、文本缩进符等富文本基础功能。//定义默认颜色​...///用户自定义颜色解析。_flutter 富文本

新一代异步IO框架——io_uring 架构-程序员宅基地

文章浏览阅读30次。近年来,Linux社区开发了一种新的异步IO框架,称为io_uring。io_uring通过提供高度可扩展和高性能的异步IO接口,有效地解决了传统异步IO框架中的一些性能瓶颈和限制。io_uring已经成为许多高性能应用程序的首选异步IO框架,为开发者提供了更好的IO处理能力。io_uring 架构是建立在Linux内核之上的,它使用了一组新的系统调用和内核机制,以提供高性能和低延迟的异步IO操作。io_uring的设计目标是提供一种简单而强大的接口,使得开发者可以轻松地利用异步IO的优势。

耗时一个月!期末熬夜复习整理 | 计算机网络(谢希仁第七版)大合集【知识点+大量习题讲解】_计算机网络期末复习题-程序员宅基地

文章浏览阅读2.5w次,点赞204次,收藏1.8k次。期末计网满绩计划教材:计算机网络(第七版)谢希仁版目录1. 概述2. 物理层3. 数据链路层(次重点)4. 网络层(重点)5. 运输层(重点)6. 应用层7. 网络安全最后1. 概述第一章概述2. 物理层第二章物理层3. 数据链路层(次重点)第三章数据链路层4. 网络层(重点)第四章网络层5. 运输层(重点)第五章运输层6. 应用层第六章应用层7. 网络安全稍后发布最后小生凡一,期待你的关注。..._计算机网络期末复习题

随便推点

Apache Kafka 可视化工具调研_kafka-console-ui-程序员宅基地

文章浏览阅读3k次。Apache Kafka 可视化工具调研_kafka-console-ui

如何编译部署独立专用服务端(Standalone Dedicated Server)【UE4】_ue4 独立服务器搭建-程序员宅基地

文章浏览阅读1.4k次。一、下载源码及编译原文链接首先需要unrealengine官网上注册并加入github开发组才有权限进入下面地址。https://github.com/EpicGames/UnrealEngine/tags注意:编译专用服务器,只能用源码编译版本的引擎,安装版本的引擎无法编译Server。打开页面后下载一个最新的release版本,解压出来后先运行Setup.bat,会自动下载资源..._ue4 独立服务器搭建

Hadoop 序列化机制_hadoop final-程序员宅基地

文章浏览阅读493次。序列化是指将结构化对象转化为字节流以便在网络上传输或者写到磁盘上进行永久存储的过程,反序列化是指将字节流转回结构化对象的逆过程序列化用于分布式处理的两大领域,进程间通信和永久存储。在Hadoop中,系统中多个节点上进程间的通信是通过“远程过程调用”(remote procedure call, RPC)实现的。RPC将消息序列化成二进制流后发送到远程节点,远程节点接着将二进制流饭序列化为原始..._hadoop final

tinymce富文本编辑器实现本地图片上传_tinymce images_upload_handler-程序员宅基地

文章浏览阅读5.7k次,点赞3次,收藏6次。在开发过程中使用tinymce富文本编辑器,发现他的图片上传默认是上传网络图片那么如何实现上传本地图片呢,上官网逛一圈,发现其实很简单在官网中找到下面这张图片,并且有相关的例子这里,我使用了自定义函数images_upload_handler (blobInfo, success, failure) { const url = 'uploadImg' ..._tinymce images_upload_handler

SpringCloud-拜托!面试请不要再问我Spring Cloud底层原理实战_spring cloud +sql springcloud底层组件-程序员宅基地

文章浏览阅读2.6k次,点赞5次,收藏14次。上一篇我们说到《拜托!面试请不要再问我Spring Cloud底层原理》,我们大概了解了Spring Cloud中各个组件的作用以及其背后实现的原理。但是俗话说得好,实践是检验真理的唯一标准。这一篇我们动手实践一下,即搭建一个包含订单服务、库存服务、仓库服务、积分服务的微服务架构项目。一、项目的工程结构工程名 服务名 端口号 shop-parent 父工程 ..._spring cloud +sql springcloud底层组件

安装及配置py-faster-rcnn(亲测且详细)-程序员宅基地

文章浏览阅读819次。Ubuntu16.04下编译py-faster-rcnn全过程,在本机上试验成功,亲测有效,清晰总结踩过的坑,常见问题及解决方案一并给出_py-fast