首页 > 图的算法专题——最小生成树

图的算法专题——最小生成树

概要:

  1. Prim算法
  2. Kruskal算法

 

1、Prim算法

算法流程:

(1)对图G(V,E)设置集合S来存放已被并入的顶点,然后执行n次(2)(3)

(2)每次从未并入顶点集合中选择与集合S最近的一个顶点,访问u并将其加入集合S,同时把这条离集合S最近的边加入最小生成树中。

(3)优化松弛

 

Prim算法与Dijkstra算法使用的思想几乎完全相同,只有在数组d[]的含义上有区别。(关于Dijkstra算法具体可以看前面写的《图的算法专题——最短路径》)

Dijkstra中d[]含义为起点s到达顶点Vi的最短距离,而Prim算法d[]含义为顶点Vi与集合S的最短距离,两者区别仅在于最短距离是到 起点 还是 集合 。

 

邻接矩阵版:

 1 const int maxn=1000;
 2 const int INF=1000000000;
 3 int n,G[maxn][maxn];
 4 int d[maxm]; //顶点到集合S的距离
 5 bool vis[maxn]={ false};
 6 
 7 int prim(){ //默认0号为初始点,函数返回最小生成树的边权之和
 8     fill(d,d+maxn,INF);
 9     d[0]=0;
10     int ans=0; //边权之和
11     for(int i=0;i){
12         int u=-1,MIN=INF;
13         for(int j=0;j){
14             if(vis[j]==false&&d[j]<MIN){
15                 u=j;
16                 MIN=d[j];
17             }
18         }
19         if(u==-1) return -1;
20         vis[u]=true;
21         ans+=d[u]; //将与集合S距离最小的边加入最小生成树
22         for(int v=0;v){
23             if(vis[v]==false && G[u][v]!=INF && G[u][v]<d[v] ){  
24                 d[v]=G[u][v]; //以u为中介点可以使v离集合S更近(u已被并入集合)
25             }
26         }
27     }
28     return ans;
29 }

 

 

邻接表版:

 1 struct Node{
 2     int v,dis;  //v为目标顶点,dis为边权
 3 };
 4 vector Adj[maxn];
 5 int n,d[maxn];
 6 bool vis[maxn]={ false};
 7 int prim(){
 8     fill(d,d+maxn,INF);
 9     d[0]=0;
10     int ans=0;
11     for(int i=0;i){
12         int u=-1,MIN=INF;
13         for(int j=0;j){
14             if(vis[j]==false && d[j]<MIN){
15                 u=j;
16                 MIN=d[j];
17             }
18         }
19         if(u==-1) return -1;
20         vis[u]=true;
21         ans+=d[u];
22         for(int j=0;j){
23             int v=Adj[u][j].v;
24             if(vis[v]==false && Adj[u][j].dis< d[v]){
25                 d[v]=Adj[u][j].dis;
26             }
27         }
28     }
29     return ans;
30 }

 

2、Kruskal算法

算法流程:

(1)对所有边权从小到大排序。

(2)按边权从小到大测试所有边,如果当前测试边所连接的两个顶点不在同一个连通块中,则并入,否则舍弃。 (运用并查集)

(3)循环执行(2)直到最小生成树的边数等于总顶点数减1或是测试完所有边时结束。若结束时边数不为顶点数减1,则图不连通。

 

 1 const int MAXV=110;
 2 const int MAXE=10010;
 3 int father[MAXV];
 4 int findFather(int x){
 5     int a=x;
 6     while(x!=father[x]){
 7         x=father[x];
 8     }
 9     while(a!=father[a]){
10         int z=a;
11         a=father[a];
12         father[z]=x;
13     }
14     return x;
15 }
16 struct edge{
17     int u,v; //边的两个端点编号
18     int cost; //边权
19 }E[MAXE];
20 bool cmp(edge a,edge b){
21     return a.cost<b.cost;
22 }
23 int kruskal(int n,int m){  //n为顶点个数,m为图的边数
24     int ans=0,Num_Edge=0;
25     for(int i=1;i<=n;i++) father[i]=i; //假设顶点范围为1到n 
26     sort(E,E+m,cmp);
27     for(int i=0;i//枚举边
28         int faU=findFather(E[i].u);
29         int faV=findFather(E[i].v);
30         if(faU!=faV){
31             father[faU]=faV;
32             ans+=E[i].cost;
33             Num_Edge++;
34             if(Num_Edge==n-1) break;
35         }
36     }
37     if(Num_Edge != n-1) return -1;
38     else return ans;
39 }

 

转载于:https://www.cnblogs.com/Mered1th/p/10422955.html

更多相关:

  •         Apache POI是一个开源的利用Java读写Excel,WORD等微软OLE2组件文档的项目。        我的需求是对Excel的数据进行导入或将数据以Excel的形式导出。先上简单的测试代码:package com.xing.studyTest.poi;import java.io.FileInputSt...

  • 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 要取得a到b之间的...

  • 利用本征图像分解(Intrinsic Image Decomposition)算法,将图像分解为shading(illumination) image 和 reflectance(albedo) image,计算图像的reflectance image。 Reflectance Image 是指在变化的光照条件下能够维持不变的图像部分...

  • 题目:面试题39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题: cl...

  • 题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树:      5     /    2   6   /  1   3示例 1: 输入: [1,6,3,2,5] 输出...

  • 集合一直都是项目中非常常见的,我是一个Android开发者,集合对于我来说,在项目中使用的次数非常之多,因为使用的多,熟能生巧,所以这里呢!就给那些初学者整理一下Java当中常用的集合吧!   因为此篇文章是给初学者看到,所以对于集合的认识,我们就不从内存的角度去分析了,等你Java学到一定的时候,再去学习一下集合的底层实现,这会让...

  • 在编程中,常常需要集中存放多个数据。从传统意义上讲,数组是我们的一个很好的选择,前提是我们事先已经明确知道我们将要保存的对象的数量。一旦在数组初始化时指定了这个数组长度,这个数组长度就是不可变的,如果我们需要保存一个可以动态增长的数据(在编译时无法确定具体的数量),java的集合类就是一个很好的设计方案了。集合类主要负责保存、盛装其他...

  • 欧拉定理:对于互质的两个正整数$a, n$,满足$a^{φ(n)} ≡ 1  (mod n)$ 证明:   设集合$S$包含所有$n$以内与$n$互质的数,共有$φ(n)$个:$$S = { x_1, x_2, ..., x_{φ(n)} } $$   再设集合$T$:$$T = { a * x_1 \% n, a * x_...

  • binary search 二分查找 half-interval search  折半查找 logarithmic search  对数搜索 sentinel 哨兵 pivot 基准数 median 中位数,中值 partition 分割 percolate 过滤 sentinel 哨兵 linear time 线性时间...

  • 《数据结构与算法分析 C语言描述》Mark Allen Weiss著,冯舜玺译,机械工业出版社。Weiss教授的经典教材三部曲之一,其中的C语言描述版本,也就是本书,被称为20世纪最重要的30本计算机教材之一。Mark Allen Weiss,1987年在普林斯顿大学获得计算机科学博士学位,师从著名算法大师Robert Sedgew...

  • 实现12种不同的算法来跟踪视频和网络摄像头中的对象! 你会学到: 使用Python和OpenCV跟踪视频和网络摄像头中的对象 理解跟踪算法的基本直觉 实现12种跟踪算法 了解对象检测和对象跟踪之间的区别 要求 程序设计逻辑 基本Python编程 MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2...

  • 文章目录1. 算法背景2. BM(Boyer-Moore)算法2.1 坏字符规则(bad character rule)2.2 好后缀规则(good suffix shift)2.3 复杂度及完整代码3. KMP(Knuth Morris Pratt)算法3.1 好前缀 和 坏字符规则3.2 高效构建 失效函数3.3 复杂度及完整代码...

  • 文章目录前言CAP理论C consistency 一致性A availability 可用性P partition tolerance 分区容错性一致性模型弱一致性强一致性强一致性算法需要明确的问题强一致算法: 主从同步强一致性算法:多数派强一致算法:PaxosBasic PaxosMulti Paxos第一个版本:使用Propose...