最小生成树的性质

MST性质:设G = (V,E)是连通带权图,U是V的真子集。如果(u,v)∈E,且u∈U,v∈V-U,且在所有这样的边中,

(u,v)的权c[u][v]最小,那么一定存在G的一棵最小生成树,(u,v)为其中一条边。

构造最小生成树,要解决以下两个问题:
(1).尽可能选取权值小的边,但不能构成回路(也就是环)。
(2).选取n-1条恰当的边以连接网的n个顶点。

Prim算法的思想:

设G = (V,E)是连通带权图,V = {1,2,…,n}。先任选一点(一般选第一个点),首先置S = {1},然后,只要S是V的真子集,就选取满足条件i ∈S,j ∈V-S,且c[i][j]最小的边,将顶点j添加到S中。这个过程一直进行到S = V时为止。在这个过程中选取到的所有边恰好构成G的一棵最小生成树。

Prim算法代码

以 hdu 1863为例 (点击打开链接

#include<stdio.h>
#include<limits.h>
#include<string.h>
#define N 100
int n,m,map[N+][N+],v[N+],low[N+];
int prim()
{
int i,j,pos,min,s=;
memset(v,,sizeof(v)); //v[i]用来标记i是否已访问,先初始化为0,表示都未访问
v[]=; //先任选一点作为第一个点
pos=; //pos用来标记当前选的点的下标
for(i=;i<=n;i++)
low[i]=map[][i]; //用low数组存已选点到其他点的权值
for(i=;i<n;i++){
min=INT_MAX;
for(j=;j<=n;j++) //求权值最小的边
if(!v[j]&&low[j]<min){
min=low[j];
pos=j;
}
if(min==INT_MAX)
break;
s+=min;
v[pos]=;
for(j=;j<=n;j++) //更新low数组
if(!v[j]&&map[pos][j]<low[j])
low[j]=map[pos][j];
}
if(i!=n)
s=-;
return s;
}
int main()
{
int i,j,s,a,b,c;
while(scanf("%d%d",&m,&n)!=EOF){ //m为道路数,n为村庄数
if(m==)
break;
for(i=;i<=n;i++)
for(j=;j<=n;j++)
map[i][j]=INT_MAX; //先将map数组初始化为很大的值(int 最大值)
for(i=;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
map[a][b]=map[b][a]=c; //map[a][b]存的从a到b的权值
}
s=prim();
if(s==-)
printf("?\n");
else
printf("%d\n",s);
}
return ;
}

Kruskal算法思想

给定无向连同带权图G = (V,E),V = {1,2,...,n}。

(1)首先将G的n个顶点看成n个孤立的连通分支。将所有的边按权从小大排序。

(2)从第一条边开始,依边权递增的顺序检查每一条边。并按照下述方法连接两个不同的连通分支:当查看到第k条边(v,w)时,如果端点v和w分别是当前两个不同的连通分支T1和T2的端点是,就用边(v,w)将T1和T2连接成一个连通分支,然后继续查看第k+1条边;如果端点v和w在当前的同一个连通分支中,就直接再查看k+1条边。这个过程一个进行到只剩下一个连通分支时为止。此时,已构成G的一棵最小生成树。

Kruskal算法代码:

以 hdu 1863为例 (点击打开链接

 #include<cstdio>
#include<algorithm>
using namespace std;
int f[],n,m;
struct stu
{
int a,b,c;
}t[];
int cmp(struct stu x,struct stu y)
{
return x.c<y.c;
}
int find(int x) //路径压缩,找父节点
{
if(x!=f[x])
f[x]=find(f[x]);
return f[x];
}
int krus()
{
int i,k=,s=,x,y;
for(i=;i<=n;i++){
x=find(t[i].a);
y=find(t[i].b);
if(x!=y){ //最小生成树不能形成环,所以要判断它们的是否属于同一集合
s+=t[i].c;
k++;
if(k==m-) //<span style="font-family: KaiTi_GB2312;">最小生成树会形成m-1(顶点-1)条边,若已形成,则最小生成树已构成</span>
break;
f[x]=y; //将父节点更新
}
}
if(k!=m-)
s=-;
return s;
}
int main()
{
int i,s;
while(scanf("%d%d",&n,&m)!=EOF){
if(n==)
break;
for(i=;i<=n;i++)
scanf("%d%d%d",&t[i].a,&t[i].b,&t[i].c);
for(i=;i<=m;i++) //f[i]存的结点i的父亲,先将其父亲都初始化为其本身
f[i]=i;
sort(t+,t++n,cmp); //按权值从小到大排序
s=krus();
if(s==-)
printf("?\n");
else
printf("%d\n",s);
}
return ;
}

注:若顶点数为n,边为e

prim算法适合稠密图,其时间复杂度为O(n^2),其时间复杂度与边的数目无关,

而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图。


最小生成树之 prim算法和kruskal算法(以 hdu 1863为例)的更多相关文章

  1. 最小生成树之Prim算法和Kruskal算法

    最小生成树算法 一个连通图可能有多棵生成树,而最小生成树是一副连通加权无向图中一颗权值最小的生成树,它可以根据Prim算法和Kruskal算法得出,这两个算法分别从点和边的角度来解决. Prim算法 ...

  2. java实现最小生成树的prim算法和kruskal算法

    在边赋权图中,权值总和最小的生成树称为最小生成树.构造最小生成树有两种算法,分别是prim算法和kruskal算法.在边赋权图中,如下图所示: 在上述赋权图中,可以看到图的顶点编号和顶点之间邻接边的权 ...

  3. 【数据结构】最小生成树之prim算法和kruskal算法

    在日常生活中解决问题经常需要考虑最优的问题,而最小生成树就是其中的一种.看了很多博客,先总结如下,只需要您20分钟的时间,就能完全理解. 比如:有四个村庄要修四条路,让村子能两两联系起来,这时就有最优 ...

  4. 最小生成树(prim算法和kruskal算法)

    学习博客:https://www.cnblogs.com/zhangming-blog/p/5414514.html 其实就是加点法:从不属于这个集合的点中找从本集合可以找到的最小边,加入本集合 看代 ...

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

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

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

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

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

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

  8. Prim算法和Kruskal算法

       Prim算法和Kruskal算法都能从连通图找出最小生成树.区别在于Prim算法是以某个顶点出发挨个找,而Kruskal是先排序边,每次选出最短距离的边再找. 一.Prim(普里姆算法)算法: ...

  9. Prim算法和Kruskal算法的正确性证明

    今天学习了Prim算法和Kruskal算法,因为书中只给出了算法的实现,而没有给出关于算法正确性的证明,所以尝试着给出了自己的证明.刚才看了一下<算法>一书中的相关章节,使用了切分定理来证 ...

随机推荐

  1. 使用第三方CDN加速服务加载js/css

    ASP.NET MVC 3.0 http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.unobtrusive-ajax.js http://ajax.aspnet ...

  2. vimrc语法

    前言 工欲善其事,必先利其器.一个programmer必然要先有一个好的editor.vim就是一个十分强大的编辑器.它的强大之处,在于其个性化和可定制.学习vim,就像学习Linux,学习perl, ...

  3. 使用二维NDRange workgroup

    作为初学者一直,经过多次的上网搜索你一定会看到迈克老狼的向量加法的示例,不知道你是否和我一样,刚开始并不是很准确的知道他的add.cl写的代码的意思,源码如下: #pragma OPENCL EXTE ...

  4. 【解决】笔记本发射WiFi

    这个百度一下一大堆 .. 不过还是希望自己总结一发适合自己的 (*^__^*)  废话不多说,开始 基于几个bat (1)CreateWlan.bat netsh wlan set hostednet ...

  5. 转载:Java多线程中join方法的理解

    转载自:http://uule.iteye.com/blog/1101994 thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A ...

  6. UIView frame, bounds and center

    http://stackoverflow.com/questions/5361369/uiview-frame-bounds-and-center Since the question I asked ...

  7. Python运行机制

    闲来无事,简单画了一下Python的运行机制,纯属娱乐:

  8. PAT 1012. The Best Rank

    To evaluate the performance of our first year CS majored students, we consider their grades of three ...

  9. mysql出现Got error 28 from storage engine错误

    今天晚上碰到app数据库出错Got error 28 from storage engine 服务程序出现这样的错误 Sql.Data---Error writing file '/tmp/ML2ig ...

  10. oninput,onpropertychange,onchange的用法和区别

    1.前言 由于工作需要,需实现一个类似于微博输入框的功能,在用户动态输入文字的时候,修改提示“您还可以输入XX字”.如下图所示: 因此,稍微研究了一下oninput,onpropertychange, ...