最小生成树概念:

一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。 最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。最小生成树其实是最小权重生成树的简称。

prim:

概念:普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之和亦为最小。

实现过程:

图例 说明 不可选 可选 已选(Vnew

此为原始的加权连通图。每条边一侧的数字代表其权值。 - - -

顶点D被任意选为起始点。顶点ABEF通过单条边与D相连。A是距离D最近的顶点,因此将A及对应边AD以高亮表示。 C, G A, B, E, F D

下一个顶点为距离DA最近的顶点。BD为9,距A为7,E为15,F为6。因此,FDA最近,因此将顶点F与相应边DF以高亮表示。 C, G B, E, F A, D
算法继续重复上面的步骤。距离A为7的顶点B被高亮表示。 C B, E, G A, D, F

在当前情况下,可以在CEG间进行选择。CB为8,EB为7,GF为11。E最近,因此将顶点E与相应边BE高亮表示。 C, E, G A, D, F, B

这里,可供选择的顶点只有CGCE为5,GE为9,故选取C,并与边EC一同高亮表示。 C, G A, D, F, B, E

顶点G是唯一剩下的顶点,它距F为11,距E为9,E最近,故高亮表示G及相应边EG G A, D, F, B, E, C

现在,所有顶点均已被选取,图中绿色部分即为连通图的最小生成树。在此例中,最小生成树的权值之和为39。 A, D, F, B, E, C, G

算法模板:

#include<stdio.h>
#include<string.h>
#include <iostream>
#include <bits/stdc++.h>
#define IO ios::sync_with_stdio(false);\
cin.tie();\
cout.tie();
#define MAX 0x3f3f3f3f
using namespace std;
int logo[];//用来标记0和1 表示这个点是否被选择过
int map1[][];//邻接矩阵用来存储图的信息
int dis[];//记录任意一点到这个点的最近距离
int n;//点个数
int prim()
{
int i,j,now;
int sum=;
/*初始化*/
for(i=; i<=n; i++)
{
dis[i]=MAX;
logo[i]=;
}
/*选定1为起始点,初始化*/
for(i=; i<=n; i++)
{
dis[i]=map1[][i];
}
dis[]=;
logo[]=;
/*循环找最小边,循环n-1次*/
for(i=; i<n; i++)
{
now=MAX;
int min1=MAX;
for(j=; j<=n; j++)
{
if(logo[j]==&&dis[j]<min1)
{
now=j;
min1=dis[j];
}
}
if(now==MAX)
break;//防止不成图
logo[now]=;
sum+=min1;
for(j=; j<=n; j++)//添入新点后更新最小距离
{
if(logo[j]==&&dis[j]>map1[now][j])
dis[j]=map1[now][j];
}
}
if(i<n)
printf("?\n");
else
printf("%d\n",sum);
}
int main()
{
while(scanf("%d",&n),n)//n是点数
{
int m=n*(n-)/;//m是边数
memset(map1,0x3f3f3f3f,sizeof(map1));//map是邻接矩阵存储图的信息
for(int i=; i<m; i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(c<map1[a][b])//防止重边
map1[a][b]=map1[b][a]=c;
}
prim();
}
}

Kruskal算法:

1.概览

  Kruskal算法是一种用来寻找最小生成树的算法,在剩下的所有未选取的边中,找最小边,如果和已选取的边构成回路,则放弃,选取次小边。

2.实现过程

1).记Graph中有v个顶点,e个边

2).新建图Graphnew,Graphnew中拥有原图中相同的e个顶点,但没有边

3).将原图Graph中所有e个边按权值从小到大排序

4).循环:从权值最小的边开始遍历每条边 直至图Graph中所有的节点都在同一个连通分量中  if 这条边连接的两个节点于图Graphnew中不在同一个连通分量中   添加这条边到图Graphnew

  图例描述:

首先第一步,我们有一张图Graph,有若干点和边

将所有的边的长度排序,用排序的结果作为我们选择边的依据。这里再次体现了贪心算法的思想。资源排序,对局部最优的资源进行选择,排序完成后,我们率先选择了边AD。这样我们的图就变成了下图

在剩下的变中寻找。我们找到了CE。这里边的权重也是5

依次类推我们找到了6,7,7,即DF,AB,BE。

下面继续选择, BC或者EF尽管现在长度为8的边是最小的未选择的边。但是现在他们已经连通了(对于BC可以通过CE,EB来连接,类似的EF可以通过EB,BA,AD,DF来接连)。所以不需要选择他们。类似的BD也已经连通了(这里上图的连通线用红色表示了)。最后就剩下EG和FG了。当然我们选择了EG。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m,sum;
struct node
{
int start,end,power;//start为起始点,end为终止点,power为权值
} edge[];
int pre[]; int cmp(node a, node b)
{
return a.power<b.power;//按照权值排序
} int find(int x)//并查集找祖先
{
if(x!=pre[x])
{
pre[x]=find(pre[x]);
}
return pre[x];
} void merge(int x,int y,int n)//并查集合并函数,n是用来记录最短路中应该加入哪个点
{
int fx=find(x);
int fy=find(y);
if(fx!=fy)
{
pre[fx]=fy;
sum+=edge[n].power;
}
}
int main()
{
while(~scanf("%d", &n), n)//n是点数
{
sum=;
m=n*(n-)/;//m是边数,可以输入
int i;
int start,end,power;
for(i=; i<=m; i++)
{
scanf("%d %d %d", &start, &end, &power);
edge[i].start=start,edge[i].end=end,edge[i].power=power;
}
for(i=; i<=m; i++)
{
pre[i]=i;
}//并查集初始化
sort(edge+, edge+m+,cmp);
for(i=; i <= m; i++)
{
merge(edge[i].start,edge[i].end,i);
}
printf("%d\n",sum);
}
return ;
}

最小生成树详解 prim+ kruskal代码模板的更多相关文章

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

    边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...

  2. 最小生成树算法详解(prim+kruskal)

    最小生成树概念: 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. 最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里 ...

  3. (原创)最小生成树之Prim(普里姆)算法+代码详解,最懂你的讲解

    Prim算法 (哈欠)在创建最小生成树之前,让我们回忆一下什么是最小生成树.最小生成树即在一个待权值的图(即网结构)中用一个七拐八绕的折线串连起所有的点,最小嘛,顾名思义,要权值相加起来最小,你当然可 ...

  4. 【算法】关于图论中的最小生成树(Minimum Spanning Tree)详解

    本节纲要 什么是图(network) 什么是最小生成树 (minimum spanning tree) 最小生成树的算法 什么是图(network)? 这里的图当然不是我们日常说的图片或者地图.通常情 ...

  5. 最小生成树(prim&kruskal)

    最近都是图,为了防止几次记不住,先把自己理解的写下来,有问题继续改.先把算法过程记下来: prime算法:                  原始的加权连通图——————D被选作起点,选与之相连的权值 ...

  6. 最小生成树 Prim Kruskal

    layout: post title: 最小生成树 Prim Kruskal date: 2017-04-29 tag: 数据结构和算法 --- 目录 TOC {:toc} 最小生成树Minimum ...

  7. 最小生成树算法 prim kruskal两种算法实现 HDU-1863 畅通工程

    最小生成树 通俗解释:一个连通图,可将这个连通图删减任意条边,仍然保持连通图的状态并且所有边权值加起来的总和使其达到最小.这就是最小生成树 可以参考下图,便于理解 原来的图: 最小生成树(蓝色线): ...

  8. 最小生成树之Prim Kruskal算法(转)

    最小生成树 首先,生成树是建立在无向图中的,对于有向图,则没有生成树的概念,所以接下来讨论的图均默认为无向图.对于一个有n个点的图,最少需要n-1条边使得这n个点联通,由这n-1条边组成的子图则称为原 ...

  9. BFS详解

    广度优先搜索详解          1. 也称宽度优先搜索,顾名思义,就是将一棵树一层一层往下搜.算法首先搜索和s距离为k的所有顶点,然后再去搜索和S距离为k+l的其他顶点.BFS是一种完备策略,即只 ...

随机推荐

  1. ASP.NET MVC5(五):身份验证、授权

    使用Authorize特性进行身份验证 通常情况下,应用程序都是要求用户登录系统之后才能访问某些特定的部分.在ASP.NET MVC中,可以通过使用Authorize特性来实现,甚至可以对整个应用程序 ...

  2. 【开源】做了一个WinForm窗体的投影组件,能够为窗口添加影子效果

    最近手头上的项目终于忙得差不多了,想起好久没有更新了的NanUI,再看着每天QQ群未读消息闪烁的标志,突然才发现似乎愧对了群里各位喜爱NanUI的朋友们.于是乎,就想趁这几天有时间,好好的修复一下Na ...

  3. Sqlserver 2005 跨数据库 导入数据

    --Sqlserver 2005 跨数据库 导入数据:--SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/O ...

  4. top命令总结

    top命令主要用来观察和收集运行在系统上的进程的一些有用信息.ps只是一个快照,是ps命令执行的那一瞬间的系统中进程的快照.top则可以用于持续观察. 第一步,在命令行键入top,回车进入top管理界 ...

  5. 常用html标签的只读写法

    <a href="baidu.com" onclick="event.returnValue=false;">百度</a> a链接的只读 ...

  6. 【Android Developers Training】 72. 缩放一个视图

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  7. git的使用[转]

    本节内容 github介绍 安装 仓库创建& 提交代码 代码回滚 工作区和暂存区 撤销修改 删除操作 远程仓库 分支管理 多人协作 github使用 忽略特殊文件.gitignore 为什么要 ...

  8. Ionic Demo 解析

    Ionic Demo 解析 index.html 解析 1.引入所需要的类库 <link rel="manifest" href="manifest.json&qu ...

  9. Servlet启动的时机

    Servlet启动的时机有两个:1.在用户第一次请求时:2.在web应用启动之时. 在web.xml 文件中配置 格式 <servlet> <servlet-name>**** ...

  10. 基于Dapper的分页实现,支持筛选,排序,结果集总数,非存储过程

    简介 之前事先搜索了下博客园上关于Dapper分页的实现,有是有,但要么是基于存储过程,要么支持分页,而不支持排序,或者搜索条件不是那么容易维护. 代码 首先先上代码: https://github. ...