- 浏览: 604610 次
- 来自: ...
文章分类
最新评论
-
lgh1992314:
相同的元素呢
一种离散化方法 -
HelloSummerR:
圆心的位置是随机的,于是圆的部分会落到canvas外,那样就显 ...
HTML5 Canvas学习笔记(1)处理鼠标事件 -
hlstudio:
好久没见到sokuban了,这有个java版的,带源码,可以参 ...
求推箱子的最小步数(java) -
肖泽文:
太好了,谢谢你。。有中文注释!
HTML5 推箱子游戏过关演示动画 -
swm8023:
删除操作,将最后一个叶子节点插入后也有可能上浮吧
彻底弄懂最大堆的四种操作(图解+程序)(JAVA)
prim算法是用来实现图最小生成树的2种常用方法之一,Prim算法的主要步骤如下:
1.设图的顶点集为V,首先选取一个点作为起始点,比如说1顶点,加入到U集合中
2.在所有u∈U,v∈V-U的边(u,v)∈E中,找一条权最小的边(u,v),将此边加进集合T中,并将此边的非U中顶点加入U中。此步骤的功能是在边集E中找一条边,要求这条边满足以下条件:首先边的两个顶点要分别在顶点集合U和V-U中,其次边的权要最小。找到这条边以后,把这条边放到边集T中,并把这条边上不在U中的那个顶点加入到U中。
3:如果U=V,则算法结束;否则重复步骤2。可以把本步骤看成循环终止条件。
我们可以算出当U=V时,步骤2共执行了n-1次(设n为图中顶点的数目),T中也增加了n-1条边,这n-1条边就是需要求出的最小生成树的边。
例题:给出t组数据,每组数据给出图的顶点数n,然后下面是n*n的无向图邻接矩阵表示,求最小生成树中权最大的边的权值。样例如下:
Sample Input
1
3
0 990 692
990 0 179
692 179 0
Sample Output
692
解法一:Prim算法代码
解法二、kruskal算法
kruskal算法其实也是和prim算法一样求无向图的最小生成树,也属于贪心算法,不过prim算法的复杂度为O(n^2),适用于稠密图,而kruskal算法的复杂度为O(eloge),适用于稀疏图。
kruskal算法描述很容易理解,如下
1.设连通网N=(V,{E}),令最小生成树初始状态为只有n个顶点而无边的非连通图T=(V,{F}),每个顶点自成一个连通分量
2.在E中选取代价最小的边,加入到T中,若它的添加使T 中产生回路,则舍去此边,选取下一条代价最小的边
3.依此类推,直至T中有 n-1 条边为止
Kruskal算法牵涉到集合操作,包括集合的建立和集合的合并,这里用并查集解决。
初始化:把每个节点所在结合初始化为自身。
查找:查找元素所在的集合,即根节点
合并:将两个在不同集合的元素合并为一个集合,应将树深度小的合并到深度大的上面或将子孙少的合并到子孙多的上面。
源码下载:
1.设图的顶点集为V,首先选取一个点作为起始点,比如说1顶点,加入到U集合中
2.在所有u∈U,v∈V-U的边(u,v)∈E中,找一条权最小的边(u,v),将此边加进集合T中,并将此边的非U中顶点加入U中。此步骤的功能是在边集E中找一条边,要求这条边满足以下条件:首先边的两个顶点要分别在顶点集合U和V-U中,其次边的权要最小。找到这条边以后,把这条边放到边集T中,并把这条边上不在U中的那个顶点加入到U中。
3:如果U=V,则算法结束;否则重复步骤2。可以把本步骤看成循环终止条件。
我们可以算出当U=V时,步骤2共执行了n-1次(设n为图中顶点的数目),T中也增加了n-1条边,这n-1条边就是需要求出的最小生成树的边。
例题:给出t组数据,每组数据给出图的顶点数n,然后下面是n*n的无向图邻接矩阵表示,求最小生成树中权最大的边的权值。样例如下:
Sample Input
1
3
0 990 692
990 0 179
692 179 0
Sample Output
692
解法一:Prim算法代码
import java.util.Scanner; public class Main{ private int prim[][];//图的邻接矩阵 private boolean visit[];//记录顶点是否被访问,即是否加入到了顶点集U private int Len[]; //Len[i] 记录顶点集U到i的最短距离,即U中所有点到i的距离之最小者。 private int n;//顶点数 int ans; public Main(int n,int[][] prim){ this.n=n; this.prim=prim; visit=new boolean[n+1];//开始时都未访问 Len=new int[n+1]; } private int prim_solve(int xx){ int minx;int k=0; ans = -1; for (int i = 1; i <= n; i++) { Len[i] = prim[xx][i]; } Len[xx] = 0; visit[xx] = true; //此时U中只有起点xx for(int i = 1; i< n; i++) // 注意:因为xx起点已经访问过,所以只需再访问n-1个 { minx = Integer.MAX_VALUE; for(int j = 1; j <= n; j++ ) //在所有u∈U,v∈V-U的边(u,v)∈E中,找一条权最小的边(u,v) { //这里找的是:与顶点集U相邻的距离最小值 if ( !visit[j] && Len[j] < minx) { minx= Len[j]; k = j; } } visit[k] = true; //找到,加入U if (ans < minx) //保存最短路径中最大的一条边 { ans = minx; } //i=1时,U中只有起点xx和新加入的k,Len[j]与prim[k][j]比较:就是比较xx到j的距离和新加入U的k顶点到j的距离 //之后,Len[j]就是U到j的最短距离啦,这样把U中所有顶点看成一个,Len[j]就是U到j(V-U中任意一个)的最短距离 //以此类推,i>1 时,每次都把原来的顶点集U到j的距离和新加入的k到j的距离比较,这样得到了新U到j的最短距离 //从而,就得到了新U到V-U中任一顶点的距离,保存在 Len中 for (int j = 1; j <= n; j++) { if ( !visit[j] && Len[j] > prim[k][j]) { Len[j] = prim[k][j]; } } } return ans; } public static void main(String[] args){ Scanner in=new Scanner(System.in); int T=in.nextInt(); while((T--)>0){ int n=in.nextInt(); int[][] prim=new int[n+1][n+1]; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j ++){ prim[i][j]=in.nextInt(); } Main m=new Main(n,prim); System.out.printf("%d\n",m.prim_solve(1)); //以第一个顶点开始,也可以是其他 } } }
解法二、kruskal算法
kruskal算法其实也是和prim算法一样求无向图的最小生成树,也属于贪心算法,不过prim算法的复杂度为O(n^2),适用于稠密图,而kruskal算法的复杂度为O(eloge),适用于稀疏图。
kruskal算法描述很容易理解,如下
1.设连通网N=(V,{E}),令最小生成树初始状态为只有n个顶点而无边的非连通图T=(V,{F}),每个顶点自成一个连通分量
2.在E中选取代价最小的边,加入到T中,若它的添加使T 中产生回路,则舍去此边,选取下一条代价最小的边
3.依此类推,直至T中有 n-1 条边为止
Kruskal算法牵涉到集合操作,包括集合的建立和集合的合并,这里用并查集解决。
初始化:把每个节点所在结合初始化为自身。
查找:查找元素所在的集合,即根节点
合并:将两个在不同集合的元素合并为一个集合,应将树深度小的合并到深度大的上面或将子孙少的合并到子孙多的上面。
import java.util.Scanner; import java.util.Arrays; public class Main{ private int father[]; private int son[]; private Edge e[]; private int n;//结点个数 private int l;//边的数目 public Main(int n,int l,Edge[] e){ this.n=n; this.l=l; this.e=e; father=new int[n]; son=new int[n]; for(int i = 0; i < n; ++i){ father[i] = i;//将每个顶点初始化为一个集合,父节点指向自己。 son[i]=1;//初始化每个父节点的儿子数为1 } } public int unionsearch(int x){ //查找根结点 return (x == father[x]) ? x : unionsearch(father[x]); } public boolean join(int x, int y){ //合并 int root1, root2; root1 = unionsearch(x); root2 = unionsearch(y); if(root1 == root2){ //为环 return false; } else if(son[root1] >= son[root2]){ father[root2] = root1; son[root1] += son[root2]; } else { father[root1] = root2; son[root2] += son[root1]; } return true; } public int kruskal(){ int ans=0; int ltotal=0; Arrays.sort(e); //按权值由小到大排序 for(int i = 0; i < l; ++i) { if(join(e[i].a, e[i].b)==true) { ltotal++; //边数加1 ans= e[i].weight; //记录 } if(ltotal == n - 1) //最小生成树条件:边数=顶点数-1 { return ans; } } return 0; } public static void main(String[] args){ Scanner in=new Scanner(System.in); int temp=0; int T=in.nextInt(); while((T--)>0){ int k=0; int n=in.nextInt(); Edge[] e=new Edge[n*(n-1)/2]; for(int i = 0; i < n; i++){ for(int j = 0; j < n; j ++){ if(i<j){//只读取上三角 e[k]=new Edge(i,j,in.nextInt()); k++; }else{ temp=in.nextInt(); } } } Main m=new Main(n,k,e); System.out.printf("%d\n",m.kruskal()); } } } class Edge implements Comparable { int a; //边的一个顶点,从数字0开始 int b; //边的另一个顶点 int weight; //权重 Edge(int a,int b,int weight){ this.a=a; this.b=b; this.weight=weight; } @Override public int compareTo(Object o){ Edge m = (Edge)o; int result=(int)(this.weight - m.weight); if(result>0) return 1; else if(result==0) return 0; else return -1; } }
源码下载:
- java2485.zip (2.4 KB)
- 下载次数: 6
发表评论
-
图的深搜+回溯练习题:POJ2197
2013-01-18 15:53 1681POJ 2197题意: 给定n个城市及其之间的距离,以及距 ... -
图的练习题(有解答)
2012-12-27 22:23 26581. 填空题 ⑴ 设无向图G ... -
邻接表实现图的广搜和深搜(java模板)
2012-12-11 17:04 2465//邻接表实现图的广搜和深搜(java模板) impor ... -
邻接矩阵实现图的广搜和深搜(java模板)
2012-12-10 20:37 1923经常要用到,放到这里备用!! //邻接矩阵实现图的广搜和深搜 ... -
如何求无向图的最小环
2012-11-13 19:02 2799POJ1734 题意:给定一个N个点的无向图,求一个最小环(各 ... -
深度优先搜索输出有向图中的所有环(JAVA)
2012-11-06 14:22 9626如图:求出有向图的所有环。 import java.uti ... -
三种算法(Floyd、Dijkstra、SPFA)求单源点最短路径。
2012-11-05 13:15 1865题(HDU2544): 在每年的校赛里,所有进入决赛 ... -
Dijkstra算法解HDU1874
2012-11-05 10:15 1369Dijkstra算法是用来解 ... -
SPFA算法求单源最短路径
2012-11-04 23:00 1945很多时候,给定的图存在负权边,这时类似Dijkstra等算法 ... -
图解Bellman-Ford算法
2012-11-03 19:39 5941Bellman-Ford算法: ... -
Bellman-Ford算法教学PPT
2012-11-03 12:06 1457Dijkstra算法是处理单源最短路径的有效算法,但它 ... -
昆虫的同性恋
2012-11-01 19:21 1399题目大意: 输入一个数t,表示测试组数。然后每组第一行两 ... -
拓扑排序入门练习
2012-11-01 16:51 1586拓扑排序简单来说 ... -
并查集入门精讲,实例2个(JAVA)
2012-10-30 14:47 4074一、什么是并查集 ... -
无前趋的顶点优先的拓扑排序方法(JAVA)
2012-10-28 20:20 1883无前趋的顶点优先的拓扑排序方法 该方法的每一步总是输 ... -
图的邻接表存储及遍历(JAVA)
2012-10-10 10:58 5427为图的每个顶点所发出的边建立一个单链表,用一顶点数组存储 ... -
弗洛伊德(Floyd)算法求任意两点间的最短路径
2012-10-01 07:46 6307Floyd-Warshall算法(Floyd-Warsha ... -
单源最短路径( Dijkstra算法)JAVA实现
2012-09-14 14:30 9129单源最短路径问题,即在图中求出给定顶点到其它任一顶 ... -
深度优先搜索与有向无环图的拓扑排序(java实现)
2012-09-11 13:05 5549当每个任务有前后置关系时,需要找到一种满足前后置关系的路 ... -
最小生成树:Kruskal(克鲁斯卡尔)算法实现(java)
2012-09-01 20:50 2636算法描述:Kruskal(克鲁斯卡尔)算法需要对图的边进行访问 ...
相关推荐
1. **引言**:介绍最小生成树的概念,以及Prim和Kruskal算法的基本思想。 2. **算法描述**:详细解释两种算法的步骤,包括伪代码或流程图。 3. **实现细节**:展示如何用编程语言(如C++、Java或Python)实现这两种...
### 使用Prim和Kruskal算法构建最小生成树 在图论中,最小生成树(Minimum Spanning Tree, MST)是一个非常重要的概念。对于一个连通的无向图来说,如果存在一个子图,它包含原图的所有顶点,并且这些顶点通过边...
总的来说,Prim和Kruskal算法都是解决最小生成树问题的有效方法,它们各有优劣,适用于不同的图类型。在实际应用中,可以根据具体情况选择合适的算法,或者结合其他方法,如Edmonds-Karp算法,以提高效率。通过学习...
本文将详细介绍两种经典算法来解决最小生成树问题:Prim算法和Kruskal算法,并以C语言实现为例进行讲解。 ### Prim算法 Prim算法是一种贪心算法,其基本思想是从一个初始节点开始,逐步添加最短的边,直到连接到...
prim算法 Kruskal算法分别实现最小生成树
在通信网理论作业3-最小生成树这个项目中,你可能会学习如何用MATLAB编写代码,实现Prim和Kruskal算法,并对给定的网络图数据进行最小生成树的构造。这将涉及到数据结构的设计、图的遍历以及最小生成树的验证等编程...
### Kruskal算法求最小生成树的Java实现 #### 一、Kruskal算法简介 Kruskal算法是一种用于寻找图中的最小生成树(Minimum Spanning Tree, MST)的算法。最小生成树是指在一个加权无向图中,连接所有顶点形成的树,...
在实际应用中,PRIM算法常与Kruskal算法一起被提及,Kruskal算法是另一种解决最小生成树问题的方法,它通过选择权值最小的边并避免形成环来构建树。两者各有优劣,适用于不同的数据结构和场景。 总之,PRIM算法是...
(1)、实验题目:给定一个地区的n 个城市间的距离网,用Prim算法或Kruskal算法建立最小生成树,并得到的最小生成树的代价。 (2)、实验要求: 1、城市间的距离网采用的邻接矩阵表示,邻接矩阵的存储结构定义采用...
### 使用Prim算法实现最小生成树 #### 一、最小生成树简介 最小生成树(Minimum Spanning Tree, MST)是指在一个加权的无向图中找到一棵包含所有顶点的生成树,使得所有边的权重之和最小。最小生成树在实际应用中...
win32控制台程序 vs2010以上编译运行通过 在main函数里定义图,然后调用2个封好的函数用2种不同的算法输出最小生成树 大连理工大学软件学院数据结构上机题
### 最小生成树Kruskal算法详解 #### 算法背景与定义 最小生成树(Minimum Spanning Tree,...尽管在处理稠密图时可能不如Prim算法高效,但Kruskal算法的简单性和易于理解使其成为学习图算法和数据结构的一个好例子。
最小生成树问题在图论中是一项基础而重要的任务,它涉及到如何从一个加权无向图中找到一棵包括所有顶点的树,使得这棵树的所有边的权重之和尽可能小。Kruskal算法就是解决这一问题的一种有效方法,由Joseph B. ...
图的深度优先搜索,广度优先搜索,最小生成树算法,包括kruskal、prim算法的代码,以及详细的注释。深度优先应用递归、广度优先搜索利用队列、kruskal利用STL中的关联容器set、prim算法利用二叉堆结构进行优化。
// 该函数使用邻接矩阵存储结构,通过Prim算法构建最小生成树 } ``` ##### 2.2.2 邻接表存储 ```c void MiniSpanTree_PRIM(ALGraph G, VertexType u) { // 代码实现省略,参见给定文件 // 该函数使用邻接表存储...
综上所述,最小生成树是图论中的核心问题,Prim算法和Kruskal算法是解决该问题的两种高效方法。在C++中,这两个算法都可以利用标准库提供的功能来实现,从而在复杂度和空间效率上达到较好的平衡。理解并熟练掌握这些...
常见的最小代价生成树算法有Kruskal算法和Prim算法。 Kruskal算法的具体步骤如下: 1. **边的排序**:将图中的所有边按照权重从小到大进行排序。这一步可以通过各种排序算法实现,如快速排序、归并排序等。在这里...
理解并熟练运用普里姆算法,不仅可以解决最小生成树的问题,还能为学习其他图算法如Kruskal算法打下基础,同时也对理解和优化复杂网络系统有重要意义。在数据结构和算法的学习过程中,掌握这些基本算法对于提升编程...
最小生成树Kruskal和Prim算法讨论 最小生成树(Minimum Spanning Tree,MST)是图论中的一种基本概念,指的是连接所有顶点的生成树中权值最小的那棵树。Kruskal算法和Prim算法是两种常用的构造MST的算法,这两种...