最小树形图

合集下载

图(最小生成树2009级)1

图(最小生成树2009级)1

6 V2 3
V1
5 V4 2
1 5 5 V3 6 4 V5 6 V6
克鲁斯卡尔(Kruskual)算法的基本步骤 克鲁斯卡尔(Kruskual)算法的基本步骤 初始时最小生成树只包含图的n个顶点, 1) 初始时最小生成树只包含图的n个顶点,每个 顶点为一棵子树; 顶点为一棵子树; 2) 选取权值较小且所关联的两个顶点不在同一子 树的边,将此边加入到最小生成树中; 树的边,将此边加入到最小生成树中; 重复2 即得到包含n个顶点和n 3) 重复2)n-1次,即得到包含n个顶点和n-1条边 的最小生成树。 的最小生成树。
V1 V2 V3 V4 V5 V6 5 INF INF 6 1 V1 0 5 INF 3 INF 0 V2 6 V3 1 V4 5 V5 INF 5 INF 3 0 5 6 4 5 0 INF 2 6 INF 0 6 4 2 6 0
v1 v3
U
v2 v4 v5 v6
V-U
V6 INF INF
顶点vi到顶点集U权最小边 权最小边数组MST[vi]:顶点 到顶点集 权最小边 顶点 权最小边数组 距离数组Dist[vi]:顶点 到顶点集 权最小边的 顶点vi到顶点集U权最小边的 距离数组 顶点 权值(顶点 到顶点集U的距离 顶点vi到顶点集 的距离) 权值 顶点 到顶点集 的距离
6
V1 5
5 6 1
v1
2 U V-U
v1 v3
U
V2
3
V3
6
5 V4 4
V5
V6
v2 v4 v5 v6
V-U
普鲁姆算法基本步骤 分别为已在生成树中的顶点集合 、 分别为已在生成树中的顶点集合和 设U、 MST分别为已在生成树中的顶点集合和 边集合。 边集合。 1)初始时,设U={u0},MST=φ; )初始时, , φ 2)在所有 ∈U 、v∈V-U的边中选择一条权值最 )在所有u∈ ∈ 的边中选择一条权值最 小的边,不妨设为(u,v); 小的边,不妨设为( ; 3)将v加入 ;(u,v)加入 加入U; 加入MST, ) 加入 加入 , 4)重复 、3),直到 为止; )重复2)、 ,直到U=V为止; 为止

最小树形图——朱刘算法学习笔记

最小树形图——朱刘算法学习笔记

最⼩树形图——朱刘算法学习笔记问题描述给定⼀张⽆向图和⼀个根r,求出⼀个n-1条边的⼀张⼦图,使得从r出发可以到达任意⼀个点,同时使得所有选择的边权之和最⼩。

根据最⼩树形图的定义,这张图的除了根的每⼀个点都必须有且仅有⼀个⼊度。

那么我们可以贪⼼⼀点,对于除了根的所有点都找出⼀条连向它的边且边权最⼩,称作这个点的代表边,并把这些边权加⼊答案中。

然后我们找出了⼀张图,这张图中每个点都只有⼀个⼊度。

如果不算根的话,它应当是⼀个外向基环树森林。

然后我们找到所有的环,把它们缩成⼀个点。

再去扫描不在环内的边,假设有u->v,那么这条边的边权要减掉v的代表边权。

因为v是⼀个环,如果继续连u->v的边的话,相当于是把原来v的⽗亲断开,再连上u。

于是我们就完成了缩点,⼀直做下去,知道图中没有环。

⽆解就是图中除了根有点没有⼊度。

代码细节1、初始化,我们令id[]表⽰这个点在那个环⾥,top[]表⽰环顶(找环时⽤),mi[]表⽰代表边的边权,cnt表⽰环数。

2、找环的时候,因为是⼀颗外向基环树,所以我们对于每个点记录father,这样father就变成了内向基环树,这样可以⽅便找环。

3、没有和其他点组成环的让它⾃⼰成为⼀个环。

4、每做完⼀轮之后要更新⼀下点数和根。

代码#include<iostream>#include<cstdio>#define N 109#define M 10009#define inf 2e9using namespace std;int tot,top[N],id[N],cnt,mi[N],n,m,fa[N],r;long long ans;inline int rd(){int x=0;char c=getchar();bool f=0;while(!isdigit(c)){if(c=='-')f=1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}return f?-x:x;}struct edge{int from,to,l;}e[M];inline void add(int u,int v,int l){e[++tot].to=v;e[tot].l=l;e[tot].from=u;}inline bool solve(){while(1){for(int i=1;i<=n;++i)id[i]=top[i]=0,mi[i]=inf;for(int i=1;i<=m;++i)if(e[i].to!=e[i].from&&e[i].l<mi[e[i].to])fa[e[i].to]=e[i].from,mi[e[i].to]=e[i].l;int u=0;mi[r]=0;for(int i=1;i<=n;++i){if(mi[i]==inf)return0;ans+=mi[i];for(u=i;u!=r&&top[u]!=i&&!id[u];u=fa[u])top[u]=i;if(u!=r&&!id[u]){id[u]=++cnt;for(int v=fa[u];v!=u;v=fa[v])id[v]=cnt;}}if(!cnt)return1;for(int i=1;i<=n;++i)if(!id[i])id[i]=++cnt;for(int i=1;i<=m;++i){int num=mi[e[i].to];e[i].from=id[e[i].from];e[i].to=id[e[i].to];if(e[i].from!=e[i].to)e[i].l-=num;}n=cnt;r=id[r];cnt=0;}}int main(){n=rd();m=rd();r=rd();int u,v,w;for(int i=1;i<=m;++i){u=rd();v=rd();w=rd();add(u,v,w); }if(solve())cout<<ans;else puts("-1");return0;}。

数据结构15--最小生成树PPT课件

数据结构15--最小生成树PPT课件

proc Union(i,j,c:longint); /*合并i和j所在集合 */
Var x,y:longint;
{ x←top(i); y←top(j); 点j所在子树的根*/
/*分别取出顶点i和顶
if x<>y Then { inc(ans,c);f[y]←x;}; /*若i 和j分属于两棵子树,则该边权计入最小生成树的权和, 两棵子树合并*/
Writeln(ans);
显然, Kruskal算法的效率取决于边数m,因此适用与
稀疏图。
.
②、Prim算法
集合A中的边总是只形成单棵树,每次添加到 树中的边都是使树的权尽可能小的边。
.
设 d[i]—顶点i与生成树相连的最短边长; ba[i]—顶点i在生成树的标志; w[i,j]—(i,j)的边长。若图中不存在边 (i,j),则w[i,j]=∞ min—所有未在生成树的顶点的最小距离 值
top←f[i]; /*返回顶点i所在并查集的代表 顶点*/ };/*top*/
.
通过过程Union(i,j,c)合并顶点i和顶点j所 在的两棵树
现有边权为c的边(i,j)。若该边的两个端点 分属于两棵树,顶点i和顶点j所在子树的根分别 为x和v,则(i,j) 加入最小生成树,合并两棵树 (即顶点i和顶点j所在的并查集)。
for j←1 to n do
if not ba[j]and(d[j]<min) then { k←j;min←d[j] }; /*then*/
if min= maxint then { ans←-1;break;};/*若这样的顶点不存 在,则无解退出*/
ans←ans+min;ba[k]←true;/*最小距离值min计入生成树的权和, 顶点k进入生成树*/

02最小生成树

02最小生成树

范例:制造系统的分组技术
建模
设用Mi表示需由机器i加工的零件集,对任 意两台机器i,j, 定义相异度:
(i, j) | Mi M j | | Mi M j |
建模
(i, j) | Mi M j | | Mi M j |
“”:对称差, 分子:在机器i但不在机器j上加工,或在机 器j但不在机器i上加工的零件数。 分母:或在机器i,或在机器j上加工的零件数。 显然 01
最小生成树
一些常见的树形结构
无向树的定义
无向树: 连通无回路的无向图 平凡树: 平凡图 森林: 每个连通分支都是树的非连通的无向图 树叶: 树中度数为1的顶点 分支点: 树中度数2的顶点 例如
(a)
(b)
子图
定义设G=<V,E>, G=<V,E>是2个图(同为无向图,或同 为有向图) 若VV且EE, 则称G为G的子图, G为G的母图, 记作 GG 若GG 且V=V, 则称G为G的生成子图 设VV且V, 以V为顶点集, 以两端点都在V中的所有 边为边集的G的子图称作V的导出子图, 记作G[V] 设EE且E, 以E为边集, 以E中边关联的所有顶点为 顶点集的G的子图称作E的导出子图, 记作G[E]
范例:制造系统的分组技术
分组技术是设计制造系统的一种方法,它把生 产零件的机器分组,相应地把需生产的零件分类,使 零件跨组加工的情形尽量少,最理想的情况是使每个 零件的加工,都在组内完成。 假设有13种零件,需在9台机器上加工。在各台 机器上加工的零件号在下表中给出。
范例:制造系统的分组技术
机器 加工 的零 件 1 2,3, 7,8, 9,12 ,13 2 2,7, 8,11 ,12, 3 1,6 表 4 5 3,5, 3,7, 10 8,9, 12, 13 6 5 7 4,10 8 4,10 9 6

最小树与最小树形图(数学建模)讲解

最小树与最小树形图(数学建模)讲解

最小树与最小树形图(数学建模)讲解一、最小树的定义及性质1. 定义:最小树,又称最小树,是指在给定的带权无向图中,包含图中所有顶点的一个树形结构,且树中所有边的权值之和最小。

2. 性质:(1)最小树中不存在回路;(2)对于最小树中的任意两个顶点,它们之间有且仅有一条路径;(3)最小树中边的数量等于顶点数量减一;(4)在最小树中添加任意一条边,都会形成一条回路;(5)最小树不唯一,但权值之和相同。

二、求解最小树的方法1. Prim算法Prim算法是一种贪心算法,其基本思想是从图中的一个顶点开始,逐步添加边和顶点,直到形成最小树。

具体步骤如下:(1)初始化:选择一个顶点作为最小树的起点,将其加入最小树集合;(2)迭代:在最小树集合和非最小树集合之间,寻找一条权值最小的边,将其加入最小树集合;(3)重复步骤2,直到所有顶点都加入最小树集合。

2. Kruskal算法Kruskal算法同样是一种贪心算法,其基本思想是将图中的所有边按权值从小到大排序,然后依次选择权值最小的边,判断是否形成回路,若不形成回路,则将其加入最小树集合。

具体步骤如下:(1)初始化:将所有顶点视为独立的树;(2)按权值从小到大排序所有边;(3)迭代:选择权值最小的边,判断其是否形成回路,若不形成回路,则将其加入最小树集合;(4)重复步骤3,直到所有顶点都在同一棵树中。

三、最小树形图的定义及求解方法1. 定义:最小树形图,又称最优树形图,是指在给定的有向图中,找到一个包含所有顶点的树形结构,使得树中所有边的权值之和最小。

2. 求解方法:朱刘算法(Edmonds' Algorithm)朱刘算法是一种用于求解最小树形图的算法,其基本思想是通过寻找图中的最小权值环,进行收缩和扩展操作,最终得到最小树形图。

具体步骤如下:(1)寻找最小权值环;(2)对最小权值环进行收缩操作,将环中的顶点合并为一个新顶点;(3)在新图中寻找最小树形图;(4)将新图中的最小树形图扩展回原图,得到原图的最小树形图。

图的常用算法——最小生成树

图的常用算法——最小生成树

TE= {(V1,V4)5,(V4,V2)3 ,(V4,V6)7,
(V6,V3)2 ,(V3,V5)6 } LW= {(V4,V7)15
9
第六次 U={ V1,V4,V2 ,V6,V3 ,V5,V7 } TE= {(V1,V4)5,(V4,V2)3 ,(V4,V6)7, (V6,V3)2 ,(V3,V5)6},(V4,V7)15 } LW= { }
3
5
7
20
所以最小生成树由GE数组中的1,2,3,5,7 边组成。 2012-1-10
2012-1-10
10
2012-1-10
11
(4)算法如下: Procedure Prim(GA,CT); begin for I:=1 to n-1 do { 给CT赋初值,对应第0次的LW值 } [ CT[I].from :=1 ; ct[I].end: =I+1 ; ct[I].w:=GA[1, i+1 ]; for k:=1 to n-1 do { 进行n-1次循环,求出最小生成树的第K条边 } ①[ min:=maxint ; m:=k ; for j:=k to n-1 do if ct[j].w < min then min:=ct[j].w ; m:=j; ] ② if m<> k then ct[k] 与ct[m] 的交换 { 将最短边调到第K单元 }
1. 从图“G”的选取一个顶点放到“G’” 中,因只有一个顶点,因此该图是连通 的; 2. 以后每加入一个顶点,都要加入以该点 为顶点与已连通的顶点之中的一个顶点 为端点的一条边,使其既连通而不产生 回路,进行n-1次后,就产生G’,在G’ 中有n个顶点,n-1条边且不产生回路。
二、图的最小生成树

最小生成树问题(共7张PPT)

最小生成树问题(共7张PPT)

个,所以支撑树是有不唯一]。
C n1 m
求最小树的Kruskal算法
赋权的连通图G=(V,E)中m=|E|,n=|V|,
S1:对E中各边的权排序,设 w1≤w2≤…≤wm,wi=w(ei)
S2:初始化: w←0,T←φ,k←1,t←0
S3:若t=n-1则转S6,否则转S4
Y
N
T’←T∪{ek}
T’成圈? N END
Y
T←T+ {ek},
k←k+1 w←w+wk,
t←t+1,k←k+1
用Kruskal算法求最小树
用Kruskal算法(避圈法)求赋权连通图G的最小树
V2
5
V6
Kruskal法盯住边,而Prim法更注意顶点:
T为最小树,w为T的权。
4
T={v1,v2,v3,v5}
Prim法求最小支撑树 E的权排序w1≤w2≤…≤wm w←0,T←φ,k←1,t←0
对要m让条程边序的读边懂长“图排”,序S程3,:序m如个何元判素断排是序否较成好“的圈算”?法谈是何基容于易分,治时策间略、的空快间速复排杂序性(Q绝u不ick应S小or看ting),其时间复杂性是O(m㏒m)。
min S2:初始化:w←0,T←φ,k←1,t←0 设: {w(vv )}w(vv ) 简对称m条最边小的树边或长最排短序树,[管vvm线ij个 铺ST 元设素]。排序较好的i算法j是基于分治策略的快l速排k序(Quick Sorting),其时间复杂性是O(m㏒m)。
S4:若T∪{ek}有圈则k←k+1转S4,否则 转S5
S5: T←T∪{ek},w←w+wk, t←t+1, k←k+1,转S3

最小生成树

最小生成树

03
Prim算法
int a[maxn][maxn],d[maxn],n,m,ans; bool v[maxn]; void prim(){ memset(d,0x3f,sizeof(d)); memset(v,0,sizeof(v)); d[1]=0; for(int i=1;i<n;i++){ int x=0; for(int j=1;j<=n;j++){ if(!v[x]&&(x==0||d[j]<d[x])) x=j; } v[x]=1; for(int y=1;y<=n;y++){ if(!v[y]) d[y]=min(d[y],a[x][y]); } } } int main(){ cin>>n>>m; memset(a,0x3f,sizeof(a)); for(int i=1;i<=n;i++) a[i][i]=0; for(int i=1;i<=m;i++){ int x,y,z; cin>>x>>y>>z; a[y][x]=a[x][y]=min(a[x][y],z); } prim(); for(int i=2;i<=n;i++) ans+=d[i]; cout<<ans; return 0; }
04
例题
PART FOUR
04
例题
tyvj 1391 泼水节 poj 1639 Picnic Planning poj 2728 最有比率生成树
没了
THANK YOU FOR WATCHING
02
Kruskal算法

斯坦纳树算法

斯坦纳树算法

斯坦纳树算法
斯坦纳树算法,也称为“终极斯坦纳树算法”,是一种用于解决带权图中的最小树形图问题的算法。

该算法具有时间复杂度为O(n^3 * 2^n)的特点,因此适用于小型图和中等规模的图,但在大型图上会出现运行时间过长的问题。

斯坦纳树算法的基本思想是将原图中的顶点集合划分成若干个
子集,然后对每个子集构建一棵最小树形图,最后将所有子集的最小树形图合并成一棵最终的最小树形图。

该算法的核心在于如何构建子集的最小树形图,这通常使用DP(动态规划)的方式进行求解。

具体而言,斯坦纳树算法的步骤如下:
1.将所有边的权值取对数,并对原图做一些预处理,以提高算法效率。

2.对于每个子集S,使用DP的方式计算S中所有点到S中某个点的最短距离,记为d(S,v),其中v是S中任意一个点。

3.对于每个子集S,将S中所有点连成一棵生成树,使得该树的根节点为S中某个点,且所有连边的权值之和等于d(S,v)。

4.通过枚举所有的子集S,计算每个子集的最小树形图,并记录下最小树形图的权值。

5.将所有子集的最小树形图合并成一棵最终的最小树形图。

需要注意的是,斯坦纳树算法只适用于有向图,且存在一些限制条件,如原图必须联通等。

此外,该算法在实际应用中,可能需要结合其他算法一起使用,以解决一些特殊情况下的问题。

第二节 最小树

第二节 最小树

v1 23 v6 28 v5 25 17
v2
1
v7
4
9 16 v4
15 v3 3
v1 23 v6 28 v5 25 17
v2
1
v7
4
9 v3 3 v4
v1 23 v6 28 v5 25 17
v2
1
v7
4
9 v3 3 v4
v1 23 v6 28 v5 17
v2
1
v7
4ห้องสมุดไป่ตู้
9 v3 3 v4
v1 23 v6 28 v5 17
第二节
最小树(树 支撑树)
树是一类极其简单而很有用的图。 定义(连通图)如果图中的任意两点 之间至少存在一条通路,则称图为连 通图,否则为不连通图。 定义(树)一个无圈的连通图称为树。 如果一个无圈的图中每一个分支都是 树,则称图为森林
树的性质: 1 在图中任意两点之间必有一条而且只有 一条通路。 2 在图中划去一条边,则图不连通,故树 是使图保持连通且具有最少边数的一种图 形。 3 在图中不相邻的两个顶点之间加一条边, 可得一个且仅得一个圈。 4 图中边数有ne=p-1(p为顶点数)
• 树是一种简单而且有用的图。早在1847年 克希霍夫研究电网络时,便发展了有关树 的理论。树在分子结构、电网络分析及企 业管理、优化设计等方面都有很重要的作 用。
例如5个顶点构成的无圈连通图是下列树枝 形状。“树”的名称即由此而来。
树是实际活动中最常用的图。 下图表示由通信线路连接起来的逐级辐射通信网,还 可以理解为图书目录分类、质量指标因果分析图等。
例3 某地新建5处居民点,拟修道 路连接5处,经勘测其道路可铺成 如图所示(边上数据为铺设费 用),为使5处居民点都有道路相 连,问至少要铺几条路且总造价 最少?

最小生成树例题详解

最小生成树例题详解

最小生成树例题详解最小生成树(Minimum Spanning Tree,简称 MST)是一种图论中的算法,用于在一个加权连通图中找到一棵包含所有顶点且边权值之和最小的生成树。

下面是一个常见的最小生成树例题:给定一个由五只兔子和它们的家组成的奴隶图,如下图所示:```1 2 3 4 5/ / /6 7 8 9 10 11/ / /2 4 6 8 10 12```要求找到一棵包含所有顶点且边权值之和最小的生成树。

首先,我们需要遍历整个图,将每个节点的度数表示出来,度数等于该节点到其他节点的距离。

我们可以用度数最小的节点来代替这个节点。

接下来,我们需要计算每个节点到根节点的度数。

如果某个节点到根节点的度数大于等于它的度数,那么它就不是最小生成树的一部分,我们需要继续寻找。

最后,我们需要计算每个节点的边权值之和。

我们可以用度数最小的节点来代替这个节点,然后遍历该节点的邻居节点,计算它们的边权值之和。

以下是Python代码实现:```pythondef Minimum Spanning Tree(graph):# 遍历整个图,将每个节点的度数表示出来,度数最小为0for node in graph:度数 = [float(edge[node]) for edge ingraph.get_edges(node)]if度数[0] <= 0:return None# 找到最小生成树root = node = Nonefor node in graph.nodes():if root is None:if not any(edge[node] for edge in graph.get_edges(node)): root = nodebreakelse:# 度数最小的节点来代替该节点if not any(edge[node] for edge in graph.get_edges(node)): root = nodebreak# 计算该节点到根节点的度数度数 = [float(edge[node]) for edge ingraph.get_edges(node)]if度数[0] <= 0:return None# 找到连接到该节点的所有边neighbors = [node for edge in graph.get_edges(node) if edge[1] >= 0]# 计算该节点的边权值之和neighbors_sum = sum(度数)# 找到边权值之和最小的节点if neighbors_sum < neighbors_sum.min():root = nodebreakreturn root```在此算法中,我们使用了邻接表(neighbors table)来维护每个节点的邻居节点。

最小树形图

最小树形图

一.最小树形图最小树形图,就是给有向带权图中指定一个特殊的点root,求一棵以root为根的有向生成树T,并且T中所有边的总权值最小。

最小树形图的第一个算法是1965年朱永津和刘振宏提出的复杂度为O(VE)的算法。

判断是否存在树形图的方法很简单,只需要以v为根作一次图的遍历就可以了,所以下面的算法中不再考虑树形图不存在的情况。

在所有操作开始之前,我们需要把图中所有的自环全都清除。

很明显,自环是不可能在任何一个树形图上的。

只有进行了这步操作,总算法复杂度才真正能保证是O(VE)。

首先为除根之外的每个点选定一条入边,这条入边一定要是所有入边中最小的。

现在所有的最小入边都选择出来了,如果这个入边集不存在有向环的话,我们可以证明这个集合就是该图的最小树形图。

这个证明并不是很难。

如果存在有向环的话,我们就要将这个有向环缩成一个人工顶点,同时改变图中边的权。

假设某点u在该环上,并设这个环中指向u的边权是in[u],那么对于每条从u出发的边(u, i, w),在新图中连接(new, i, w)的边,其中new为新加的人工顶点; 对于每条进入u的边(i, u, w),在新图中建立边(i, new, w-in[u])的边。

为什么入边的权要减去in[u],这个后面会解释,在这里先给出算法的步骤。

然后可以证明,新图中最小树形图的权加上旧图中被收缩的那个环的权和,就是原图中最小树形图的权。

上面结论也不做证明了。

现在依据上面的结论,说明一下为什么出边的权不变,入边的权要减去in [u]。

对于新图中的最小树形图T,设指向人工节点的边为e。

将人工节点展开以后,e指向了一个环。

假设原先e是指向u的,这个时候我们将环上指向u的边 in[u]删除,这样就得到了原图中的一个树形图。

我们会发现,如果新图中e的权w'(e)是原图中e的权w(e)减去in[u]权的话,那么在我们删除掉in[u],并且将e恢复为原图状态的时候,这个树形图的权仍然是新图树形图的权加环的权,而这个权值正是最小树形图的权值。

【转】【最小树形图】有向图的最小生成树【朱刘算法】

【转】【最小树形图】有向图的最小生成树【朱刘算法】

【转】【最⼩树形图】有向图的最⼩⽣成树【朱刘算法】这篇⽂章挺好的。

每⾏还有注释QAQ,kuangbin的模板⾥并没有万能节点;万能节点好像是在不定根的时候的拓展。

要点:1.求所有边权和sum;2.以0点为万能节点向所有点建⼀条权值为sum的边;3.记得sum++;保证⽐所有边权值总和⼤⼀点;4.判断条件为(ans==-1 || ans-sum>=sum) //ans-sum是除去虚根的最⼩树形图的最短路径,如果这个距离⽐所有的边权值和sum还⼤,说明还有另外的边由虚点发出,故说明此图不连通5.答案即为ans-sum;做了POJ的⼀道题,总是WA,不知道为什么,后来去看了,才知道,原来有向图的最⼩⽣成树与⽆向图不⼀样,它得是从某个点出发能遍历到其他所有点的才⾏,以此为条件,我们学习到了最⼩树形图。

与很多其他⼈的讲解不⼀样吧,我把我看了博客后⾃⼰的思路分享出来,关于什么是最⼩树形图。

我们知道的既然要建⽴最⼩树形图,就要理解什么是最⼩树形图,(概念好难懂啊,还是⾃⼰写的清楚明⽩),我们从某⼀点出发(或者是固定点),能通过它跑完所有点的最⼩花费,就是最⼩树形图了。

那么,怎么去搭建最⼩树形图?会有⼈看到关于最⼩弧这样的讲法,诶!确实是这样的,但是你们理解什么是最⼩弧吗?我们想构建⼀颗最⼩⽣成树的时候,就是找到这样的最优解的边逐条放进去的(Kruskal算法思想),但是这也是⼀样的,我们找到所有⾮根节点的最⼩⼊边,先把这样的所有⼊边给加进来,那么得到的⼀幅图,可能还真是不完全,要是遇到了个环,岂不是有趣,或者呢,压根就⾛不完!不就GG?所以,就这样就被我们想出了两个需要判断的条件了。

把所有的最⼩⼊边先加起来,我们得到了⼀个花⾥胡哨的图,可能它就是多个环的集合,也许恰好是答案,这都是不确定的,若是恰好是已经没有环了,那么这就是答案了;反之,就是有环,那么,我们得到的边,就不⼀定是所有的点构在⼀起的图(也许会成为森林这样的情况),那么,把环搜索起来吧,我们把⼀个环搜索成⼀个点,然后对于它(新点——即所谓的缩点)的⼊边,我们建⽴新边的时候,需要考虑到我们得删除原来在这幅图⾥的改点的⼊边(就是我们已经存⼊了这个原节点的⼊边了,但是,它却构成了环,说明不是我想要的解),所以,新边的权值就是原权值减去终点节点的最⼩⼊边。

16.2最短树

16.2最短树
V2 15 V1 30 40 25 V5 10 30 20 15 V3 10 V4
例题2 一个赋权图如下, 例题 一个赋权图如下,请生成其最小 生成树。 生成树。 (x1,x2),(x2,x5),(x2,x4),(x3,x4)
最小生成树也可为: 最小生成树也可为: (x1,x2),(x2,x5),(x2,x4),(x2,x3)
V5 10 V4 V2
最长树: Kቤተ መጻሕፍቲ ባይዱuskal算法中 最长树:将Kruskal算法中,每次加 算法中, 入最短边,改成每次加入最长边, 入最短边,改成每次加入最长边,即 可实现. 可实现.
V2 17
采用Kraskal方法 方法: 采用 方法 (v1,v2)=12,(v2,v3)=15,(v2,v4)=17,(v4,v5)=17
V5 25 36 V1 40 12 30 17 15 V3 19 V4
V2 17
采用Prim方法为 方法为: 例题 采用 方法为 (v1,v2)=15, 最近是v 离{v1,v2}最近是 4=(v2,v4)=20, 最近是 最近的是v 离{v1,v2, v4}最近的是 5=(v5,v4)=10 最近的是 最近的是v 离{v1,v2, v4 , v5}最近的是 3=(v3,v4)=10 最近的是
V2 15 V1 30 40 25 V5 10 30 20 15 V3 10 V4
Prime算法:首先任选一结点 构成 Prime算法:首先任选一结点V0构成 算法 集合U,然后不断在 然后不断在V-U中选一条到 中选一条到U 集合 然后不断在 中选一条到 中某点(比如 最短边(v,r)进入 , 比如v)最短边 进入T, 中某点 比如 最短边 进入 U=U+r,直到 ,直到U=V. 书上提供的算法:以已生成的部分树 以已生成的部分树t 书上提供的算法 以已生成的部分树 为基准,最早进入该树的边是与 最早进入该树的边是与v1距 为基准 最早进入该树的边是与 距 离最短的边,然后依次计算与 然后依次计算与t距离最 离最短的边 然后依次计算与 距离最 短的点,将该对应边添入树中 将该对应边添入树中,直到有 短的点 将该对应边添入树中 直到有 n-1条边为止 条边为止. 条边为止
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

poj3164
最小树形图,就是给有向带权图中指定一个特殊的点root,求一棵以root为根的有向生成树T,并且T 中所有边的总权值最小。

最小树形图的第一个算法是1965年朱永津和刘振宏提出的复杂度为O(VE)的算法。

判断是否存在树形图的方法很简单,只需要以v为根作一次图的遍历就可以了,所以下面的算法中不再考虑树形图不存在的情况。

在所有操作开始之前,我们需要把图中所有的自环全都清除。

很明显,自环是不可能在任何一个树形图上的。

只有进行了这步操作,总算法复杂度才真正能保证是O(VE)。

首先为除根之外的每个点选定一条入边(以该点为终点的有向边),这条入边一定要是所有入边中最小的。

现在所有的最小入边都选择出来了,如果这个入边集不存在有向环的话,我们可以证明这个集合就是该图的最小树形图。

这个证明并不是很难。

如果存在有向环的话,我们就要将这个有向环所称一个人工顶点,同时改变图中边的权。

假设某点u在该环上,并设这个环中指向u的边权是in[u],那么对于每条从u出发的边(u, i, w),在新图中连接(new, i, w)的边,其中new为新加的人工顶点; 对于每条进入u的边(i, u, w),在新图中建立边(i, new, w-in[u])的边。

为什么入边的权要减去in[u](等效抵消,在还原有向生成树时是等价的),这个后面会解释,在这里先给出算法的步骤。

然后可以证明,新图中最小树形图的权加上旧图中被收缩的那个环的权和,就是原图中最小树形图的权。

(没有有向圈后就完成了算法)
上面结论也不做证明了。

现在依据上面的结论,说明一下为什么出边的权不变,入边的权要减去in [u]。

对于新图中的最小树形图T,设指向人工节点的边为e。

将人工节点展开以后,e指向了一个环。

假设原先e是指向u的,这个时候我们将环上指向u的边in[u]删除,这样就得到了原图中的一个树形图。

我们会发现,如果新图中e的权w'(e)是原图中e的权w(e)减去in[u]权的话,那么在我们删除掉in[u],并且将e恢复为原图状态的时候,这个树形图的权仍然是新图树形图的权加环的权,而这个权值正是最小树形图的权值。

所以在展开节点之后,我们得到的仍然是最小树形图。

逐步展开所有的人工节点,就会得到初始图的最小树形图了。

如果实现得很聪明的话,可以达到找最小入边O(E),找环O(V),收缩O(E),其中在找环O(V)这里需要一点技巧。

这样每次收缩的复杂度是O(E),然后最多会收缩几次呢?由于我们一开始已经拿掉了所有的自环,我门可以知道每个环至少包含2个点,收缩成1个点之后,总点数减少了至少1。

当整个图收缩到只有1个点的时候,最小树形图就不不用求了。

所以我们最多只会进行V-1次的收缩,所以总得复杂度自然是O(VE)了。

由此可见,如果一开始不除去自环的话,理论复杂度会和自环的数目有关。

要点:
首先判断连通性,若从根节点能访问到每个节点,说明存在有向生成树
其次在判断是否存在有向圈,对n个顶点找n-1个最小弧,要么某个节点的前代节点是树根,要么存在有向圈,具体处理时将整个圈收缩到首次发现存在圈的节点。

相关文档
最新文档