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为结点数) 说明:先任意找一个点标记,然后每次找一条最短的两端分别为标记和未标记的边加进来,再把未标记的点标记上.即每次加入一条合法的最短的边,每次扩展 ...
随机推荐
- gdb调试SAPI方式的php
一.修改php-fpm.conf文件 /usr/local/php/etc/php-fpm.conf pm.max_children = 1 #只产生一个进程,便于追踪 二.得到进行服务的进程号 [r ...
- 分享10个Js的小型库,效果真的很棒
1.$fx()简介:$fx()是一个轻量级的动画库,一些复杂的动画,可以由多个简单的动画效果进行组合,但是提供的是混淆压缩过的代码,对于研究动画源码的朋友可能特别不爽API:http://fx.ine ...
- 怎么找到MyEclipse->add struts capabilities
问:MyEclipse:我的工程右键可以MyEclipse->add struts capabilities之前有,后来不知怎么就没有了,谁知道怎么弄出来是struts 答:你已经add过一次了 ...
- Apache2.2+Tomcat7.0整合配置详解
一.简单介绍 Apache.Tomcat Apache HTTP Server(简称 Apache),是 Apache 软件基金协会的一个开放源码的网页服务器,可以在 Windows.Unix.Lin ...
- java jvm学习笔记三(class文件检验器)
欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验 ...
- ChineseCounter.cs 统计中文文本中常用字占比
http://www.tuicool.com/articles/qmMba2 1 using System; using System.IO; using System.Collections.Gen ...
- lightoj 1018 (状态压缩DP)
设dp[s]表示状态s下所需要的线段的个数,s的二进制中第x位为1就表示该状态下第x个点没被线段覆盖.需要预处理出来在任意两点之间连线所覆盖点的状态O(n^3),然后记忆化搜索即可. #include ...
- lightoj 1016
水题,排个序直接搞. #include<cstdio> #include<string> #include<cstring> #include<iostrea ...
- opencv 在工业中的应用:blob分析
在工业中经常要检测一副图像中物体的数量,位置,大小,面积等信息,这就要用到BLOB分析,我用OPENCV做了个BLOB分析的DEMO. (1)打开一幅图像 (2)进行参数设置,设定二值化阙值,并选择是 ...
- 浏览器中显示视频,flash等的代码处理
window.flashView=function(flash_url){ var html=''; html+='<div id="obj_flash_div">'; ...