最小生成树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)算法的更多相关文章

  1. 最小生成树(MST)Prim算法和Kruskal算法

    刚学完最小生成树,赶紧写写学习的心得(其实是怕我自己忘了) 最小生成树概念:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. 就是说 ...

  2. 【数据结构】 最小生成树(二)——kruskal算法

    上一期说完了什么是最小生成树,这一期咱们来介绍求最小生成树的算法:kruskal算法,适用于稀疏图,也就是同样个数的节点,边越少就越快,到了数据结构与算法这个阶段了,做题靠的就是速度快,时间复杂度小. ...

  3. 最小生成树---Prim算法和Kruskal算法

    Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...

  4. 转载:最小生成树-Prim算法和Kruskal算法

    本文摘自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html 最小生成树-Prim算法和Kruskal算法 Prim算 ...

  5. 最小生成树Prim算法和Kruskal算法

    Prim算法(使用visited数组实现) Prim算法求最小生成树的时候和边数无关,和顶点树有关,所以适合求解稠密网的最小生成树. Prim算法的步骤包括: 1. 将一个图分为两部分,一部分归为点集 ...

  6. 最小生成树Prim算法和Kruskal算法(转)

    (转自这位大佬的博客 http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html ) Prim算法 1.概览 普里姆算法(Pr ...

  7. 权重最小生成树的思想与Kruskal算法

    晚上做携程的笔试题,附加题考到了权重最小生成树.OMG,就在开考之前,我还又看过一遍这内容,可因为时间太紧,也从来没有写过代码,就GG了.又吃了眼高手低的亏.这不,就好好总结一下,亡羊补牢. 权重最小 ...

  8. 最小生成树——Prim算法和Kruskal算法

    洛谷P3366 最小生成树板子题 这篇博客介绍两个算法:Prim算法和Kruskal算法,两个算法各有优劣 一般来说当图比较稀疏的时候,Kruskal算法比较快 而当图很密集,Prim算法就大显身手了 ...

  9. hdu1233 最小生成树Prim算法和Kruskal算法

    Prim算法 时间复杂度:O(\(N^2\),N为结点数) 说明:先任意找一个点标记,然后每次找一条最短的两端分别为标记和未标记的边加进来,再把未标记的点标记上.即每次加入一条合法的最短的边,每次扩展 ...

随机推荐

  1. 使用powerdesigner 画图的详细说明

    一.概念数据模型概述 数据模型是现实世界中数据特征的抽象.数据模型应该满足三个方面的要求: 1)能够比较真实地模拟现实世界 2)容易为人所理解 3)便于计算机实现 概念数据模型也称信息模型,它以实体- ...

  2. c语言中较常见的由内存分配引起的错误_内存越界_内存未初始化_内存太小_结构体隐含指针

    1.指针没有指向一块合法的内存 定义了指针变量,但是没有为指针分配内存,即指针没有指向一块合法的内浅显的例子就不举了,这里举几个比较隐蔽的例子. 1.1结构体成员指针未初始化 struct stude ...

  3. 【转】iOS中16进制转10进制

    原文网址:http://www.voidcn.com/blog/u012198553/article/p-4976772.html /// 将十六进制的字符串转化为NSData - (NSData ) ...

  4. listview使用总结

    1. android给listview的item设定高度 原文网址:http://blog.csdn.net/l_serein/article/details/7403992 在item的layout ...

  5. 【转】基于Android Fragment功能的例子

    原文网址:http://blog.csdn.net/eyu8874521/article/details/8252216 通过最近空闲时候对Fragment的学习,尝试着写了一个小Demo,将在开发的 ...

  6. 巧用CSS文件愚人节恶搞(转)

    明天就是4月1日愚人节了,也就是那个可适度开玩笑.整蛊的日子了.如果你想和那些要上网的朋友或同事开个极客式玩笑,那就来试试这个国外网友Wes Bos分享的 CSS 文件吧. 一.打开浏览器的 Cust ...

  7. TortoiseSVN中分支和合并实践

    使用svn几年了,一直对分支和合并敬而远之,一来是因为分支的管理不该我操心,二来即使涉及到分支的管理,也不敢贸然使用合并功能,生怕合并出了问题对团队造成不良影响,最主要的原因是,自己对分支的目的和合并 ...

  8. HDU 5634 Rikka with Phi 线段树

    题意:bc round 73 div1 D 中文题面 分析:注意到10^7之内的数最多phi O(log(n))次就会变成1, 因此可以考虑把一段相同的不为1的数缩成一个点,用平衡树来维护. 每次求p ...

  9. 树-二叉平衡树AVL

    基本概念 AVL树:树中任何节点的两个子树的高度最大差别为1. AVL树的查找.插入和删除在平均和最坏情况下都是O(logn). AVL实现 AVL树的节点包括的几个组成对象: (01) key -- ...

  10. JqueryTips小实验,浏览器滚动条不限制

    最近做公司的项目有些地方可能需要一些小提示,于是自己建立项目研究tips.在此之前看到过一些别人写的JqueryTips,于是借鉴了一些别人的经验在此基础上我做出了一些改进. 有的同学可能使用过其他一 ...