Contents

  • 最小生成树
    • Algorithm
      • Prim
        • Code
      • Kruskal
    • Prim&KruskalPrim \& KruskalPrim&Kruskal算法的性质
    • 最小生成树的性质
      • 最小生成树的线性递增序列
    • 例题
  • 次小生成树
    • Code
    • 例题
      • 1148. 秘密的牛奶运输
      • 356. 次小生成树

最小生成树

Given a Connected-Undirected-Graph with nnn points (it may contains Negative-Edge, Self-Loop, Negative-Loop, in other words, a arbitrary graph but satisfying Connected-Undirected), you need to find a Sub-Graph which contains nnn points, being connected and its weight (the sum of all edges) is minimal amongst others.

In fact, such a Sub-Graph could be a Tree (n−1n - 1n−1 edges).
Because there may have many different Sub-Graph which share the same weight, we assert that there must exist a Tree amongst them.

There are some algorithms for getting a MST.

Algorithm

Prim

We have a tree TTT with a single arbitrary point originally, each time we add a point and a edge (which connects this new point and a point of TTT), after n−1n - 1n−1 times we will get the MST.

We stipulate AdjEdges(T)AdjEdges( T)AdjEdges(T) is the set of all adjacent edges which connect a point of TTT and a point that is not belongs to TTT.

For example, the MST is

         {b,...}|
{c,...}-----a|{d,...}+ the edges {d-c, d-f, d-e} are belong to MST.
+ {b,...} means a `Sub-Tree` of the MST, the same as {c,...} and {d,...}

Original, we set T=(a)T = (a)T=(a)

First time, (suppose that the weight of a−ba-ba−b is less than that of a−ca-ca−c and a−da-da−d), our goal is to get a−ba-ba−b, and then add it to TTT.

Property: a−ba-ba−b is the minimal edge of AdjEdges(T)AdjEdges( T)AdjEdges(T)
Because a−ba-ba−b is less than a−ca-ca−c and a−da-da−d as we assumed, so we need to prove a−ba-ba−b is less than any edge of AdjEdges(T)/{a−b,a−c,a−c}AdjEdges( T) / \{a-b, a-c, a-c\}AdjEdges(T)/{a−b,a−c,a−c}

Proof:

T: {a}------{b,...}|------{c,...}|------{d,...}

if there exists a edge a−Ba-Ba−B (B∈{b,...}B \in \{b,...\}B∈{b,...}) which is less than a−ba-ba−b, we can replace a−ba-ba−b by a−Ba-Ba−B to get a new-MST, however it has a smaller weight than the original-MST, so it raises a contradiction.
If there exists a edge a−Ca-Ca−C (C∈{c,...}C \in \{c,...\}C∈{c,...}) which is less than a−ba-ba−b, we can also replace a−ca-ca−c by a−Ca-Ca−C to get a smaller new-MST which also makes a contradiction.

More generally, if TTT contains multiple points, e.g., {a,x,y}\{a, x, y\}{a,x,y}. Now, the edge ?−b?-b?−b means there is a edge between ??? (a point of TTT) and bbb in the MST.
Supposing ?−b?-b?−b is less than ?−c,?−d?-c, ?-d?−c,?−d, and you can also prove that ?−b?-b?−b is the minimal edge of AdjEdge(T)AdjEdge( T)AdjEdge(T).

Therefore, the process of Prim is consisted of nnn steps:

  • Firstly, T=(a)T = (a)T=(a) (aaa is a arbitrary point)
  • Secondly, suppose that x−yx-yx−y is the minimal edge of AdjEdges(T)AdjEdges( T)AdjEdges(T) (xxx belongs to TTT), then we add yyy to TTT and x−yx-yx−y is a edge of MST.
  • The same as Secondly.

Code

We will use a auxiliary array Distance to finish this algorithm.

Assume that T=(a,b,c)T = (a, b, c)T=(a,b,c) at current and others undetermined points are (d,e,f)(d, e, f)(d,e,f), then Distance[d]=min(Edge[d−a],Edge[d−b],Edge[d−c])Distance[ d] = min( Edge[d-a], Edge[d-b], Edge[d-c])Distance[d]=min(Edge[d−a],Edge[d−b],Edge[d−c]), that is, the DistanceDistanceDistance of a undetermined point xxx is the minimal edge of all edges which connect xxx and a point of TTT.

Next, we iterate all undetermined points (d, e, f), find the minimal DistanceDistanceDistance (suppose it is ddd), then ddd is added to TTT, and Distance[d]Distance[d]Distance[d] is a new edge of MST.

Finally, because ddd is belongs to TTT, so Distance[e]=min(Edge[e−a],Edge[e−b],Edge[e−c])Distance[ e] = min( Edge[e-a], Edge[e-b], Edge[e-c])Distance[e]=min(Edge[e−a],Edge[e−b],Edge[e−c]) should also be updated by Edge[e−d]Edge[e-d]Edge[e−d].
… that is, iterate all undetermined points (e,f), update Distance[x]=min(self,Edge[x,d])Distance[ x] = min( self, Edge[ x, d])Distance[x]=min(self,Edge[x,d]). (ddd is the new point that added into MST).

Kruskal

Auxiliary-Property-1:
For a graph, its MST must contains eee which is the minimal edge of the graph.
(proof: e.g., a--b--c is a branch of MST, and there exists a edge a-c that is the minimal edge amongst all edges of the graph; then you can replace a--b by a-c to make the MST more optimal)

Auxiliary-Property-2:
For a graph (contains (a,b,c,d,e)(a,b,c,d,e)(a,b,c,d,e) points), when we divide its MST into two partition, e.g., if c−dc-dc−d is a edge of MST, then remove this edge, we will get two Sub-Tree of MST (denote M1,M2M1, M2M1,M2), let it be (a,b,c)(a,b,c)(a,b,c) and (d,e)(d,e)(d,e). And also divide this graph into two partition (denote G1,G2G1, G2G1,G2): one contains (a,b,c)(a,b,c)(a,b,c) points and its interior edges, another contains (d,e)(d,e)(d,e) points and its interior edges.
Then, M1M1M1 is also the MST of G1G1G1, the same as M2,G2M2, G2M2,G2.
(proof: if mmm is the MST of G1G1G1 instead of M1M1M1, then the Tree m,(c−d),m2m, (c-d), m2m,(c−d),m2 is also a MST which is less than the previous MST, this is contradictory.)

Originally, let edgesedgesedges be all edges of the graph. Stipulate min(edges)min( edges)min(edges) denotes the minimal-edge of edgesedgesedges.

  1. min(edges)min( edges)min(edges) is a edge (let its endpoints be a,ba,ba,b) of MST (according to Property-1), and divide the MST into two partition M(a),M(b)M(a), M(b)M(a),M(b);
    remove all edges that connect M(a),M(b)M(a), M(b)M(a),M(b) from edgesedgesedges, it also means you divide the original-Graph into two parts G(a),G(b)G(a), G(b)G(a),G(b) (edgesedgesedges is the edges that either belongs G(a)G(a)G(a) or belongs to G(b)G(b)G(b))
    According to Property-2, M(a)M(a)M(a) is also the MST of G(a)G(a)G(a)
  2. suppose min(edges)min(edges)min(edges) belongs to G(a)G(a)G(a), then min(edges)min(edges)min(edges) is a edge of M(a)M(a)M(a). Using the same process as the above, you will get 333 Sub-Graphs.
    Until you get nnn Sub-Graphs (each graph is a point), then the n−1n-1n−1 edges which are removed is the MST.

As a result, sort all edges at first, and iterate each edge (a,b,w)(a,b,w)(a,b,w), if a,ba, ba,b are not in a same Disjoint-Set, then www is a edge of MST (the removal-edge as mentioned above), then Merge a,ba, ba,b to the same Set.
Otherwise a,ba,ba,b is in the same Set, meaning the operation that remove a edge that connects two divided-Graph (G(a),G(b)G(a), G(b)G(a),G(b) as mentioned above)

Prim&KruskalPrim \& KruskalPrim&Kruskal算法的性质

+ The edges of the graph in Prim or Kruskal, are both undirected (bidirectional).

+ If the graph is not connected, that is consists of several connected-subgraphs G0,Gi,...G0, Gi, ...G0,Gi,... (where G0G0G0 denotes a connected-subgraph that contains point-000), Prim can only get the MST of G0G0G0 not for Gi,...Gi, ...Gi,...; while Kruskal could get all MSTs of G0,Gi,...G0, Gi, ...G0,Gi,... simultaneously.

+ Prim, Kruskal can also be used to calculate Maximal-ST, by replacing minminmin by maxmaxmax.
. Proof: ???

+ For a undirected-graph GGG, when you storing it
. In Prim, for any undirected-edge (a,b,w) (assume there is no other edges between (a,b)), you must make sure Edges[a][b] = Edges[b][a] = w in the Adjacency-Matrix. That is, one undirected-edge corresponds to two directed-edges.
. In Kruskal, you can just choose one directed-edge (a->b) to be stored in Linked-List, not necessary both sides; this is due to the mechanism of Kruskal (the disjoint-set not relates the direction of edges) Consequently, one undirected-edge just corresponds to its one directed-edge is enough.

最小生成树的性质

最小生成树的线性递增序列

We call a Sequence of a ST is a ordered sequence of edges after sorting all edges;
. 1 For any one MST, if its Sequence is a1≤a2≤...a1 \leq a2 \leq ...a1≤a2≤..., then the Sequences of all MSTs are identical to a1,a2,...a1, a2, ...a1,a2,...
. 2 More generally, for any ST, if its Sequence is b1≤b2≤...b1 \leq b2 \leq ...b1≤b2≤..., then we have bi≥aibi \geq aibi≥ai
. For instance, if a MST is 1 2 4, then there would not exist a ST (maybe MST) which is 1 1 5 or 3 3 3, due to bi≥aibi \geq aibi≥ai. But 1 3 4 (non-MST) is possible.
. This property is very important and useful, it not only shows that the sum of all edges in a MST is ≤\leq≤ that of any ST, but also implies that the maximal edge in a MST must ≤\leq≤ any ST (maybe equal, e.g., the MST is 1 2 4, a non-MST ST is 1 3 4, such cases are possible).

例题

+ 1144. 连接格点

次小生成树

Let MST be the edges e1,e2,...eme1, e2, ...eme1,e2,...em, then all inferior-MST (strictly, or non-strictly) must be the edges f1,f2,...,fmf1, f2, ..., fmf1,f2,...,fm where only one pair of edges ei≠fjei \neq fjei=fj, in other words, if we remove ei,fjei, fjei,fj, the rest two sets will form a bijection.

Let the context of the next discussion be Strictly Inferior-MST.

If we have a MST e1,e2,...,eme1, e2, ..., eme1,e2,...,em, then we iterator all edges on GGG which are not eieiei (i.e., the edges not in the MST)
For any such a edge fififi (if its endpoints are a,ba, ba,b, and the path of them in the MST are ex,ey,ezex, ey, ezex,ey,ez, the weight are 3,5,53, 5, 53,5,5)
There is a necessity: fi≥5fi \geq 5fi≥5 (if not, that is fi<5fi < 5fi<5, we move 555 from MST and add fififi, it again forms a ST whose sum less than MST;) this is a property of MST, which is no matter to inferior-MST.
. According to the property above, if the inferior-MST contains fififi, then the edges of inferior-MST must be obtained by the process: remove a edge ex/ey/ezex/ey/ezex/ey/ez from MST, and then add fififi
There are also some lemmas on the relationship between the removal edge and fififi.
1 when fi>5fi > 5fi>5, only if fififi replace the maximal edge 555, that could maybe the inferior-MST (because if fififi replace 1/31/31/3, it will get a much large ST than replacing 555)
2 otherwise fi=5fi = 5fi=5, if the inferior-MST is strictly, then we shall try to use fififi to replace the strictly inferior-maximal edge 333 (although there are multiple same maximal edges 555; e.g., the MST is 3,5,53, 5, 53,5,5 and there is only one edge 555 which not belongs to MST, so all STs with distinct sum are 3,5,53,5,53,5,5 and 5,5,55,5,55,5,5; that is, now we should choose the strictly inferior-maximal-edge 333 on the MST-path, not the non-strictly 555)

That is, we need get d1d1d1 means the maximal edge of the path a−ba - ba−b in MST, d2d2d2 means the strictly inferior-maximal edge in that path (note that, if the path is 3,5,53, 5, 53,5,5, then d1=5,d2=3d1 = 5, d2 = 3d1=5,d2=3, that is the case of strictly inferior-MST)

Code

Suppose all edges are ≥0\geq 0≥0 and we use −1-1−1 denotes a invalid-edge;

Strictly-Inferior-MST

//> get the maximal and inferior-maximal edges on the path (a-b) in the MST
pair< int, int> Get_edges( int a, int b){d1 = d2 = -1; //< d1 is the maximal-edge, d2 is the inferiore-maximalfor( auto w : Edges on the path `a-b` in MST){update( d1, d2, w);}
}void update( int & d1, int & d2, int _w){if( _w > d1){d2 = d1;d1 = _w;}else if( _w != d1){ //< d2 must `<` d1d2 = max( _w, d2);}
};
//----//> find the Strictly-Inferior-MST
ans = 0x7F7F7F7F...;
for( edge `(a-b):w` : all edges of the graph ){if( this edge on the MST){continue;}if( a == b){continue;}pair<int,int> ret = Get_edges( a, b);ASSERT_( ret.first != -1);if( w > ret.first){ans = min( mst_size - ret.first + w, ans);}else if( ret.second != -1){ans = min( mst_size - ret.second + w, ans);}
}

Non-Strictly-Inferior-MST

//> get the maximal edge on the path (a-b) in the MST
pair< int, int> Get_edges( int a, int b){d1 = -1; //< d1 is the maximal-edgefor( auto w : Edges on the path `a-b` in MST){d1 = max( d1, w);}
}
//----//> find the NonStrictly-Inferior-MST
ans = 0x7F7F7F7F...;
for( edge `(a-b):w` : all edges of the graph ){if( this edge on the MST){continue;}if( a == b){continue;}auto ret = Get_edges( a, b);ASSERT_( ret != -1);ans = min( mst_size - ret + w, ans);
}

例题

1148. 秘密的牛奶运输

problem-link

Cuz there are only N=500N = 500N=500 points, when we got the MST, we can use D1[N][N],D2[N][N]D1[N][N], D2[N][N]D1[N][N],D2[N][N] denotes the Maximal and Inferior-Maximal edge on the path (a−b)(a-b)(a−b) in the MST. More precisely, let Dfs(x)Dfs(x)Dfs(x) to get all D1[x][all],D2[x][all]D1[x][all], D2[x][all]D1[x][all],D2[x][all], then performing Dfs(all)Dfs( all)Dfs(all)

356. 次小生成树

link

Due to N=1e5N = 1e5N=1e5, the above N2N^2N2 device is infeasible here.
Cuz MST is a tree, we can use LCA algorithm which will divide a path a−ba-ba−b into several disjoint segments (is also a path essentially) s1,s2,...s1, s2, ...s1,s2,..., then we can store d1,d2d1, d2d1,d2 which represent the maximal and inferior-maximal edge for each segment sisisi, then we gather them up (d1,d2)(d1,d2)...(d1, d2) (d1, d2) ...(d1,d2)(d1,d2)... and the maximal and inferior-maximal edge on the path a−ba-ba−b must be contained in this set.


//> building `dist1, dist2`
for( int power = 0; power < power_range; ++power){if( power == 0){ptrNew_father[ nex][ power] = cur;dist1[ nex][ power] = wth;dist2[ nex][ power] = -1;continue;}int mid = ptrNew_father[ nex][ power - 1];if( (mid == -1) || (ptrNew_father[ mid][ power - 1] == -1)){ptrNew_father[ nex][ power] = -1;dist1[ nex][ power] = -1;dist2[ nex][ power] = -1;continue;}ptrNew_father[ nex][ power] = ptrNew_father[ mid][ power - 1];int _edges[ 4] = { dist1[ nex][ power - 1], dist2[ nex][ power - 1],dist1[ mid][ power - 1], dist2[ nex][ power - 1]};sort( _edges, _edges + 4);dist1[ nex][ power] = _edges[ 3];dist2[ nex][ power] = -1;for( int i = 2; i >= 0; --i){if( _edges[ i] != dist1[ nex][ power]){dist2[ nex][ power] = _edges[ i];break;}}ASSERT_( dist2[ nex][ power] < dist1[ nex][ power]);}
//----
//> get the maximal and inferior-maximal edges on the path (a-b) in MST.
pair< int, int> Get_edges( int _a, int _b){int d1 = -1, d2 = -1;ASSERT_( (_a >= 0) && (_a < ptrRef_tree->Get_pointsCount()));ASSERT_( (_b >= 0) && (_b < ptrRef_tree->Get_pointsCount()));if( ptrNew_depth[ _a] != ptrNew_depth[ _b]){if( ptrNew_depth[ _a] < ptrNew_depth[ _b]){swap( _a, _b);}for( int i = power_range - 1; i >= 0; --i){if( ptrNew_father[ _a][ i] == -1){continue;}if( ptrNew_depth[ ptrNew_father[ _a][ i]] >= ptrNew_depth[ _b]){update( d1, d2, dist1[ _a][ i]);update( d1, d2, dist2[ _a][ i]);_a = ptrNew_father[ _a][ i];}}}ASSERT_( ptrNew_depth[ _a] == ptrNew_depth[ _b]);if( _a == _b){return {d1, d2};}for( int i = power_range - 1; i >= 0; --i){if( ptrNew_father[ _a][ i] != ptrNew_father[ _b][ i]){update( d1, d2, dist1[ _a][ i]);  update( d1, d2, dist2[ _a][ i]);update( d1, d2, dist1[ _b][ i]);  update( d1, d2, dist2[ _b][ i]);//--_a = ptrNew_father[ _a][ i];_b = ptrNew_father[ _b][ i];}}ASSERT_( ptrNew_father[ _a][ 0] == ptrNew_father[ _b][ 0]);update( d1, d2, dist1[ _a][ 0]);  update( d1, d2, dist2[ _a][ 0]);update( d1, d2, dist1[ _b][ 0]);  update( d1, d2, dist2[ _b][ 0]);return {d1, d2};
}
void update( int & d1, int & d2, int _w){if( _w > d1){d2 = d1;d1 = _w;}else if( _w != d1){d2 = max( _w, d2);}
}

`Computer-Algorithm` 最小生成树MST,Prim,Kruskal,次小生成树相关推荐

  1. ReviewForJob——最小生成树(prim + kruskal)源码实现和分析

    [0]README 1)本文旨在给出 ReviewForJob--最小生成树(prim + kruskal)源码实现和分析, 还会对其用到的 技术 做介绍: 2)最小生成树是对无向图而言的:一个无向图 ...

  2. 图论总结(欧拉路+Floyd所有结点最短+Bellman-Ford算法+SPFA+Dijsktra算法+Tarjan算法+最小生成树(prim+kruskal) )

    目录 欧拉路 判断欧拉路是否存在: ​​​​​​​ 最短路: Floyd算法 : ​​​​​​​​​​​​​​ Bellman-Ford: ​​​​​​​ Dijkstra 单源最短路 先附上例题: ...

  3. 数据结构实验之图论九:最小生成树(Prim/Kruskal)

    Description 有n个城市,其中有些城市之间可以修建公路,修建不同的公路费用是不同的.现在我们想知道,最少花多少钱修公路可以将所有的城市连在一起,使在任意一城市出发,可以到达其他任意的城市. ...

  4. Kruskal/prim--最小生成树

    问题概述:已知有n个村庄以及部分村庄之间的所有公路长度,你的目标是以最短的公路使全省任意两个村庄间都可以实现公路交通,而其他公路全部废弃,求出满足条件的最短公路长度,如果没法联通,输出-1 输入样例: ...

  5. #最小生成树,prim,kruskal#poj 2560 Freckles 雀斑

    题目 求最小生成树 分析 prim & kruskal Kruskal代码 #include <cstdio> #include <cmath> #include &l ...

  6. 图论 —— 生成树 —— 次小生成树

    [概述] 对于给定的无向图 G=(V,E),设 T 是图 G 的一个最小生成树,那么,对于除 T 外的第二小的生成树 T' 即为图的次小生成树. 简单来说,最小生成树是生成树的最小解,次小生成树是生成 ...

  7. NYOJ118 修路方案 次小生成树

    修路方案 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描述 南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修路. ...

  8. 最小生成树(kruskal、prim、最小生成森林问题、严格次小生成树)

    整理的算法模板合集: ACM模板 目录 一.kruskal算法 二.prim算法 三.Boruvka算法 四.生成森林问题(K颗树) 五.最小生成树的唯一性 六.严格次小生成树 LCA优化的次小生成树 ...

  9. 求的带权图最小生成树的Prim算法和Kruskal算法

    求的带权图最小生成树的Prim算法和Kruskal算法 最小生成树的概念 最小生成树其实是最小权重生成树的简称. 一个连通图可能有多个生成树.当图中的边具有权值时,总会有一个生成树的边的权值之和小于或 ...

最新文章

  1. 测试与封装5.1.5.2
  2. 雷林鹏分享:Redis 管道技术
  3. 【一周入门MySQL—3】多表查询、子查询、常用函数
  4. 货拉拉周胜馥,这次赌“输”了?
  5. 目标检测比赛中的 trick
  6. 【实战篇】| 模拟 20 万数据快速查询 IP 归属地
  7. 安装navicat之后双击就会闪退_Adobe 2020版本,安装教程来咯
  8. 华为oj题目c语言,华为OJ机试题目——24点游戏算法
  9. go https 笔记
  10. 推特称攻击者利用其 API 匹配用户名和电话号码
  11. 【Oracle】搭建DataGuard
  12. 智能交通综合管控平台方案
  13. 7种常用数据分析方法 (下)
  14. 计算机属性中没有端口,电脑设备管理器里没有显示COM2端口是什么原因
  15. K8S实战进阶篇:一文带你深入了解K8S持久化存储解决方案
  16. VINS-Mono关键知识点总结——边缘化marginalization理论和代码详解
  17. 现实迷途 第二十章 峰回路转
  18. 终结符号和非终结符号
  19. 各版本的Hadoop安装包下载
  20. 机器学习数据集-MNIST

热门文章

  1. “武汉疫情后,中国将发生这3种改变”,17年前的非典早预言了一切
  2. python组合求和-近似值
  3. Unity3D 自学之路
  4. TFET and hybrid TFET-FinFET文章解读
  5. 百事公司携手深圳市营养学会推广“全谷物”营养
  6. 淡淡的感动——电影《听说》观后感
  7. linux系统查看usb转串口驱动,Linux usb转串口驱动
  8. 基于微信小程序的车位预约设计与实现--毕业论文
  9. 【硬核扫盲】到底什么是相干光通信?
  10. 图解最常用的10个机器学习算法