一、问题
最小生成树解决的问题如下所示:
假设要在 n 个城市之间建立通讯联络网,则连通 n 个城市只需要修建 n-1条线路,如何在最节省经费的前提下建立这个通讯网?
使用Prime算法构造最小生成树,将生成树上的边的权值累加即可得到最小值。
二、Prime算法核心思想
取图中任意一个顶点 v 作为生成树的根,之后往生成树上添加新的顶点 w。在添加的顶点 w 和已经在生成树上的顶点v 之间必定存在一条边,并且该边的权值在所有连通顶点 v 和 w 之间的边中取值最小。之后继续往生成树上添加顶点,直至生成树上含有 n-1 个顶点为止。
动态图演示:
三、算法实现(Java)
import java.util.Scanner; public class Prime { private final static int maxNodeValue=(1<<31)-1; public static void main(String[] args){ Scanner scanner=new Scanner(System.in); int[][] map=new int[101][101]; while(scanner.hasNext()){ init(map); int nodeCount=scanner.nextInt(); int edgeCount=scanner.nextInt(); for(int i=0;i<edgeCount;i++){ int node1=scanner.nextInt(); int node2=scanner.nextInt(); int edgeValue=scanner.nextInt(); map[node1][node2]=edgeValue; map[node2][node1]=edgeValue; } int cost=prime(nodeCount,map); System.out.println(cost); } } public static int prime(int nodeCount,int[][] map){ int[] lowcost=new int[101]; int cost=0; lowcost[1]=-1; for(int i=2;i<=nodeCount;i++){ lowcost[i]=map[1][i]; } for(int i=1;i<=nodeCount-1;i++){ int min=maxNodeValue; int k=0; for(int j=1;j<=nodeCount;j++){ if(min>lowcost[j]&&lowcost[j]!=-1){ min=lowcost[j]; k=j; } } cost+=min; lowcost[k]=-1; for(int j=1;j<=nodeCount;j++){ if(lowcost[j]!=-1&&lowcost[j]>map[k][j]){ lowcost[j]=map[k][j]; } } } return cost; } public static void init(int[][] map){ for(int i=0;i<map.length;i++){ for(int j=0;j<map[i].length;j++){ map[i][j]=maxNodeValue; } } } }
这里使用lowcost数组保存非生成树上的节点到生成树的最小值,每次添加一个节点到生成树,都需要刷新lowcost数组。
四、测试数据
输入
6 10
1 2 6
2 5 3
5 6 6
6 4 2
4 1 5
3 1 1
3 2 5
3 5 6
3 6 4
3 4 5
输出
15
6 10
1 2 6
2 5 3
5 6 6
6 4 2
4 1 5
3 1 1
3 2 5
3 5 6
3 6 4
3 4 5
输出
15
五、ACM
题目链接:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2144
AC代码:
import java.util.Scanner; import java.util.Map; import java.util.HashMap; public class Main { private final static int maxNodeValue=(1<<31)-1; public static void main(String[] args){ Scanner scanner=new Scanner(System.in); int[][] map=new int[101][101]; while(scanner.hasNext()){ init(map); int nodeCount=scanner.nextInt(); int edgeCount=scanner.nextInt(); for(int i=0;i<edgeCount;i++){ int node1=scanner.nextInt(); int node2=scanner.nextInt(); int edgeValue=scanner.nextInt(); if(map[node1][node2]>edgeValue){ map[node1][node2]=edgeValue; map[node2][node1]=edgeValue; } } int cost=prime(nodeCount,map); System.out.println(cost); } } public static int prime(int nodeCount,int[][] map){ int[] lowcost=new int[101]; int cost=0; lowcost[1]=-1; for(int i=2;i<=nodeCount;i++){ lowcost[i]=map[1][i]; } for(int i=1;i<=nodeCount-1;i++){ int min=maxNodeValue; int k=0; for(int j=1;j<=nodeCount;j++){ if(min>lowcost[j]&&lowcost[j]!=-1){ min=lowcost[j]; k=j; } } cost+=min; lowcost[k]=-1; for(int j=1;j<=nodeCount;j++){ if(lowcost[j]!=-1&&lowcost[j]>map[k][j]){ lowcost[j]=map[k][j]; } } } return cost; } public static void init(int[][] map){ for(int i=0;i<map.length;i++){ for(int j=0;j<map[i].length;j++){ map[i][j]=maxNodeValue; } } } }
这道题目出的实际上并不好,有默认的规则:
- 顶点的个数=最大值,顶点值一定从0开始,依次递增到最大值(顶点的个数)
- 默认从0开始加入生成树
- 默认有可能出现输入相同边两次的情况,这时候取最小值
相关推荐
总之,通过研究这个C#实现的普里姆算法,你不仅能深入理解最小生成树的概念,还能掌握如何用C#编写图算法,这对于进一步学习图论、数据结构以及算法优化都有极大的帮助。同时,这也是提升你的编程技能和问题解决能力...
最小生成树(Minimum Spanning Tree, MST)是图论中的一个重要概念,特别是在计算机科学和工程领域有着广泛应用。它指的是在给定加权无向图中,找到一个边的子集,使得这些边连接了图中的所有顶点,并且这个子集的总...
普里姆(Prim)算法是图论中的一个经典算法,用于在加权无向图中找到一棵连接所有顶点的最小生成树。最小生成树是一棵包含图中所有顶点的树,其边的权重之和尽可能小。这个算法特别适用于解决网络连接问题,如城市之间...
最小生成树是图论中的一个重要概念,用于解决网络优化问题,特别是在成本或距离最小化时。在给定的连通图中,最小生成树是一棵包括所有节点的子树,其边的权重之和是最小的。Prim算法是求解最小生成树的一种经典算法...
最小生成树是图论中的一个经典问题,主要应用于网络设计、数据通信等领域,旨在找到连接所有顶点的边集合,使得这些边的总权重最小。在这个C++实现中,我们将会探讨两种常用的算法:Prim算法和Kruskal算法。 ### ...
最小代价生成树,也称为最小生成树(Minimum Spanning Tree, MST),是图论中的一个经典问题。给定一个加权无向图,寻找一棵包含所有顶点的子图,使得这棵子图是一棵树,并且其边的权重之和最小。Kruskal算法是一种...
Prime 算法是一种常用的最小生成树算法,用于寻找无向图中的最小生成树。该算法的实现主要涉及到图论和树论两个领域。 算法原理 Prime 算法的实现基于图论和树论的基本概念。无向图可以看作是一个节点集合和边集合...
具体到提供的代码,可以看到`prime`函数实现了普里姆算法,使用一个邻接矩阵`edge`存储城市间的距离,通过不断更新最近邻接节点和最小生成树的总成本来找到最小生成树。`kruskal`函数实现了克鲁斯卡尔算法,利用并查...
1. **最小生成树**:最小生成树是连接图中所有顶点的边的集合,且这些边的总权重最小。 - **Prim算法**:Prim算法是一种贪婪算法,从一个初始顶点开始,每次选择与当前生成树距离最近的未加入顶点,并更新其他顶点...
《数学建模算法数据结构精选》是一本针对数学建模和算法实践的综合教程,尤其强调了图论和数据结构的应用。以下将详细介绍其中涉及的关键知识点。 **一、数论算法** 1. **最大公约数(GCD)**: 最大公约数是两个或多...
以上是算法大全(数据结构)的部分内容,包括了数论中的最大公约数和最小公倍数计算,以及图论中的素数判断和最小生成树的Prim和Kruskal算法。这些算法在实际编程中有着广泛的应用,如在密码学、网络设计、图形处理...
图论算法是指用于处理图结构的算法,包括最小生成树、最短路径等。 1.最小生成树 A. Prim 算法 过程prim(v0:integer); var lowcost,closest:array[1..maxn] of integer; i,j,k,min:integer; begin for i:=1 ...
最小生成树问题是图论中的经典问题,目的是找到一棵包含图中所有顶点的树,其边的权重之和最小。 A. Prim算法: Prim算法是一种贪心算法,从一个起始顶点开始,逐步添加边,每次选择与当前生成树距离最短的未...
接着,我们转向图论算法,这里主要讨论最小生成树问题: 1. Prim算法: - Prim算法是一种构造最小生成树的方法,从一个初始顶点开始,逐步添加边,使得每次添加的边连接的是当前生成树和剩余顶点中权值最小的边,...
接下来,我们转向图论算法,这里主要讨论了最小生成树的构造。最小生成树是一个无向图中连接所有顶点的边的集合,其总权重最小。Prim算法和Kruskal算法是两种常用的方法。 - Prim算法从一个起始顶点开始,逐步添加...
- **Kruskal算法**:Kruskal算法也是贪心策略,但按照边的权重递增顺序考虑边,只有当添加的边不会形成环路时才将其加入最小生成树。描述中的`kruskal`函数利用并查集数据结构来检测新边是否会形成环路,通过`find`...
数据结构实验报告的主题是解决管道铺设问题,这是一个典型的图论问题,具体来说是寻找无向网的最小生成树。最小生成树问题是图论中的一个重要概念,它的目标是在保证图连通性的前提下,找到权值总和最小的一组边,这...
1.最小生成树 A. Prim 算法: 过程 prim(v0: integer); var lowcost, closest: array[1..maxn] of integer; i, j, k, min: integer; begin for i := 1 to n do begin lowcost[i] := cost[v0, i]; closest[i] ...