MST最小生成树及克鲁斯卡尔(Kruskal)算法
最小生成树MST,英文名如何拼写已忘,应该是min spaning tree吧。假设一个无向连通图有n个节点,那么它的生成树就是包括这n个节点的无环连通图,无环即形成树。最小生成树是对边上权重的考虑,最小生成树即树的所有边上权重值之和最小,最小指权重最小,即在含有 n 个顶点的连通网中选择 n-1 条边,构成一棵极小连通子图,并使该连通子图中 n-1 条边上权值之和达到最小。专业一点的解释:在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得 w(T) 最小,则此 T 为 G 的最小生成树。
一、 克鲁斯卡尔(Kruskal)算法
克鲁斯尔卡算法的时间复杂度为O(ElogE),E为无向图中边的数目。适用于求边稀疏的网格的最小生成树。
克鲁斯卡尔算法的基本思想为:为使生成树上总的权值之和达到最小,则应使每一条边上的权值尽可能地小,自然应从权值最小的边选起,直至选出 n-1 条互不构成回路的权值最小边为止。具体作法如下:首先构造一个只含 n 个顶点的森林,即初始无向连通图G=(V,E),首先要对图中的各个边按照权值大小进行排序,这也体现了贪心算法的思想,资源排序,从而对局部最优的资源进行选择。要生成的最小生成树为T=(U,TE),然后考察G中的边的集合E,依权值从小到大从连通网中选择不使森林中产生回路的边加入到森林中去,直至该森林变成一棵树为止,这棵树便是连通网的最小生成树。
若被考察的边的两个顶点属于T的两个不同的连通分量,则将此边作为最小生成树的边加入到T中,同时把两个连通分量连接为一个连通分量;若被考察边的两个顶点属于同一个连通分量,则舍去此边,以免造成回路,如此下去,当T中的连通分量个数为1时,此连通分量便为G的一棵最小生成树。
具体代码如下:
#include "stdio.h"
#include "stdlib.h"
struct edge
{
int m;
int n;
int d;
}a[5010]; //边的结构体数组
int cmp(const void *a,const void *b) //按升序排列
{
return ((struct edge *)a)->d > ((struct edge *)b)->d;
}
int main(void)
{
int i,n,t,num,min,k,g,x[100];
printf("请输入顶点的个数:");
scanf("%d",&n); t=n*(n-1)/2; //所有可能存在的边的条数最大值
for(i=1;i<=n;i++)
x[i]=i;
printf("请输入每条边的起、末端点、权值:/n"); for(i=0;i<t;i++)
scanf("%d %d %d",&a[i].m,&a[i].n,&a[i].d); //输入每条边的权值
qsort(a,t,sizeof(a[0]),cmp);
min=num=0;
for(i=0;i<t && num<n-1;i++)
{
for(k=a[i].m;x[k]!=k;k=x[k]) //判断线段的起始点所在的集合
x[k]=x[x[k]];
for(g=a[i].n;x[g]!=g;g=x[g]) //判断线段的终点所在的集合
x[g]=x[x[g]];
if(k!=g) //如果线段的两个端点所在的集合不一样
{
x[g]=k;
min+=a[i].d;
num++;
printf("最小生成树中加入边:%d %d/n",a[i].m,a[i].n);
}
}
printf("最小生成树的权值为:%d/n",min); system("pause");
return 0;
}
另一份参考代码如下:
#include <iostream>
#include <algorithm>
using namespace std; const int maxint = 999999; typedef struct Road{
int c1, c2; // a到b
int value; // 权值
}Road; int no;
int line;//记录实际关系数
Road road[100];//设一个比较大的值,实际看输入最小生成树中:边数e=n-1
int node[101];//最小生成树:n顶点数 bool myCmp(const Road &a, const Road &b)
{
if(a.value < b.value)
return 1;
return 0;
} //node[2]=1 node[8]=1 ,node[3]=1,共同的祖先,如果(3,8)加进去,则构成回路,不要
//有点像并查集
int Find_Set(int n)
{
if(node[n] == -1)
return n;
return node[n] = Find_Set(node[n]);
} bool Merge(int s1, int s2)
{
int r1 = Find_Set(s1);
int r2 = Find_Set(s2);
if(r1 == r2)//如果相等证明构成回路,则直接返回一个0,不要把顶点加进来(下一步是加进去的)
return 0;
if(r1 < r2)
node[r2] = r1;
else
node[r1] = r2;
return 1;
} int main()
{
freopen("input.txt", "r", stdin);
//初始化全为-1
memset(node, -1, sizeof(node));
scanf("%d",&no);
scanf("%d",&line);
int i;
for(i=0; i<line; ++i)
{
cin >> road[i].c1 >> road[i].c2 >> road[i].value;
}
sort(road, road+line, myCmp);
int sum = 0, count = 0; // sum是MST的值,count是记录已使用的点数
for(i=0; i<line; ++i)
{
if(Merge(road[i].c1, road[i].c2))//如果返回的为0,则证明构成回路,不要加进
{
count ++;
sum += road[i].value;
}
if(count == no-1)//e=n-1已经连通,可以退出
break;
}
cout << sum << endl;
return 0;
}
MST最小生成树及克鲁斯卡尔(Kruskal)算法的更多相关文章
- 最小生成树(MST)Prim算法和Kruskal算法
刚学完最小生成树,赶紧写写学习的心得(其实是怕我自己忘了) 最小生成树概念:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. 就是说 ...
- 【数据结构】 最小生成树(二)——kruskal算法
上一期说完了什么是最小生成树,这一期咱们来介绍求最小生成树的算法:kruskal算法,适用于稀疏图,也就是同样个数的节点,边越少就越快,到了数据结构与算法这个阶段了,做题靠的就是速度快,时间复杂度小. ...
- 最小生成树---Prim算法和Kruskal算法
Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...
- 转载:最小生成树-Prim算法和Kruskal算法
本文摘自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html 最小生成树-Prim算法和Kruskal算法 Prim算 ...
- 最小生成树Prim算法和Kruskal算法
Prim算法(使用visited数组实现) Prim算法求最小生成树的时候和边数无关,和顶点树有关,所以适合求解稠密网的最小生成树. Prim算法的步骤包括: 1. 将一个图分为两部分,一部分归为点集 ...
- 最小生成树Prim算法和Kruskal算法(转)
(转自这位大佬的博客 http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html ) Prim算法 1.概览 普里姆算法(Pr ...
- 权重最小生成树的思想与Kruskal算法
晚上做携程的笔试题,附加题考到了权重最小生成树.OMG,就在开考之前,我还又看过一遍这内容,可因为时间太紧,也从来没有写过代码,就GG了.又吃了眼高手低的亏.这不,就好好总结一下,亡羊补牢. 权重最小 ...
- 最小生成树——Prim算法和Kruskal算法
洛谷P3366 最小生成树板子题 这篇博客介绍两个算法:Prim算法和Kruskal算法,两个算法各有优劣 一般来说当图比较稀疏的时候,Kruskal算法比较快 而当图很密集,Prim算法就大显身手了 ...
- hdu1233 最小生成树Prim算法和Kruskal算法
Prim算法 时间复杂度:O(\(N^2\),N为结点数) 说明:先任意找一个点标记,然后每次找一条最短的两端分别为标记和未标记的边加进来,再把未标记的点标记上.即每次加入一条合法的最短的边,每次扩展 ...
随机推荐
- [HDU 4828] Grids
Grids Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Subm ...
- 【转】android新建项目时 出现appcompat_v7工程错误和红色感叹号
原文网址:http://www.cnblogs.com/xiaozhang2014/p/4109856.html 最近初学android,版本是22.6.0的话,每次创建一个项目就会出现一个appco ...
- WCF学习笔记(二):简单调用
转:http://www.cnblogs.com/wengyuli/archive/2009/11/08/1598428.html 一个通信会话过程有两个部分组成,客户端和服务端,他们要进行会话就必然 ...
- java jvm学习笔记二(类装载器的体系结构)
欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 在了解java虚拟机的类装载器之前,有一个概念我们是必须先知道的,就是java的沙箱,什 ...
- java中的快捷键
Ctrl+1 快速修复(最经典的快捷键,就不用多说了)Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加)Ctrl+Alt+↑ 复制当前行到上一行(复制增加)Alt+↓ 当 ...
- 模拟post请求方法
2
- [原]AngularJS iframe打开不同域的内容时报错误
<iframe id="myFrame" ng-src="{{url}}" width="100%" height="100 ...
- wuzhicms私密下载链接生成
加载函数库:load_function('content','content'); echo private_file('http://dev.wuzhicms.com/uploadfile/2014 ...
- 在ubuntu中启用ftp服务
Vsftpd vsftpd,ftp服务端,本文转自http://wiki.ubuntu.org.cn/Vsftpd 目录 [隐藏] 1 stand alone和super daemon 2 安装 3 ...
- 【原创】tcp协议那块一些点(想到了再加)
1.3次握手 4次握手 2.那张状态图,FIN_WAIT主动关闭方,CLOSE_WAIT被动关闭方 主动关闭方发出FIN后进入FIN_WAIT,FIN_WAIT方收到了ACK和FIN,发出了ACK,则 ...