生成树
定义
一个连通图的生成树是一个极小连通子图,含有图中所有顶点,但只有构成一棵树的**(n-1)**条边
性质
有**(n-1)**条边的图不一定都是生成树;
再添一条边,必定构成环;
再少一条边,一定非连通;
带权图的最小生成树
一个带权连通无向图G,可以有不同的生成树,每棵树的所有边上的权值之和也可能不同。
图的所有生成树中具有边上的权值之和最小的树称为图的最小生成树。
最小生成树的生成规则
· 只使用网中的n-1条边来构造n个顶点的最小生成树
· 不能产生回路
· 各边上的权值的总和达到最小
两种最常用的算法
Kruskal(克鲁斯卡尔)
Prim(普里姆)算法
利用MST性质来构造最小生成树
若U集是V的一个非空子集,若(u0, v0)是一条最小权值的边,其中u0∈U, v0∈V-U;则(u0, v0)必在最小生成树上。
最小生成树——Kruskal算法
问题
G=(V,E)是一个具有n个顶点的带权连通无向图,T=(U,TE)是G的最小生成树
步骤
步骤1:构造一个只有n个顶点,没有边的非连通图
步骤2:选最小权值的边加入,且不能形成回路,直到所有顶点连通
即
按边选
1、去边留顶点
2、选权最小的
3、不成环
最小生成树——Prim算法
问题
G=(V,E)是一个具有n个顶点的带权连通无向图
T=(U,TE)是G的最小生成树,其中U是T的顶点集,TE是T的边集
步骤
步骤1:构选一个U集,一个W集(V-U)
步骤2:从某顶点u0出发,找与W集中各顶点关联的权值最小的边(u0,v),将v加入到U中,从W集中删掉
步骤3:从U集中各点,找与W集中各点关联的权值最小的边(u0, v),将v加入到U中,从W集中删掉,直到W集为空
即
按点选
1、生成U和W集
2、找U集中各点与W集中各点权最小的
3、W中去掉,加入U
最短路径
单源最短路径——Dijkstra(迪杰斯特拉)算法
单源:一顶点到其余各顶点
所有顶点间的最短路径——**Floyd(弗洛伊德)**算法
多源:任意两顶点之间
非负权值的单源最短路径(Dijkstra算法)
目的
设一有向图G=(V,E),已知各边的权值,以某指定点v0为源点,求从v0到图的其余各点的最短路径。
限定各边上的权值大于或等于0
算法
设置两个顶点的集合S和T,集合S中存放已找到最短路径的顶点,集合T中存放当前还未找到最短路径的顶点。初始状态时,集合S中只包含源点,设为v0
步骤1:初始化:先找出从源点v到各终点v0的直达路径(v0,vk),即通过一条弧到达的路径。
步骤2:选择:从这些路径中找出一条长度最短的路径(v0,u)。
步骤3:调整:对其余各条路径进行适当调整。
若在图中存在弧(u,v
k),((v
0,u) +(u,v
k) <(v
0,v) ,则以路径(v
0,v
k)代替(v
0,v
k)
在调整后的各条路径中,再找长度最短的路径,依此类推。直到所有的顶点全部加入到S中为止。
存储空间
存储图:邻接矩阵G[n] [n] (或者邻接表)
辅助数组:
数组S[n]:顶点是否已被确定最短距离
数组D[n]:每一个分量D[i]表示当前找到的从源点v到终点vi的最短路径的长度。
D[n]初始状态:
若从v0到顶点vi有边,则D[i]为该边的权值;若从v0到顶点vi无边,则D[i]为∞。
每次求得一条最短路径后,其终点v
k加入集合S,然后对所有的v
i∈ V-S,修改其dist[i]值。
数组Path[n]:记录相应顶点的前驱顶点
算法步骤
1、初始化
将源点v0加到S中,即S[v0]=true;
将v0到各个终点的最短路径长度初始化为权值,即D[i]=G.arcs [v0] [vi],(vi∈V-S);
如果v0和顶点vi之间有弧,则将vi的前驱置为v0,即Path[i]= v0,否则path[i]=-1。
2、选择下一条最短路径的终点vk,使得:
D[k]=Min{D[i]v
0∈V-S}
3、将k加到S中,即S[vk]=true。
4、更新从v0]出发到集合V-S上任一顶点的最短路径的长度,同时更改vi的前驱为vk。
若S[i]=false且D[k]+G.arcs[k] [i]<D[i],则D[i]=D[k]+ G.arcs[k] [i; Path [i]=k;。
5、重复2~4 n-1次,即可按照路径长度的递增顺序,逐个求得从 v0到图上其余各顶点的最短路径。
算法实现
//一开始主循环,每次求得vO到某个顶点v的最短路径,将v加到s集
for(i=1;i<n;++i){//对其余n-1个顶点,依次进行计算
min= MaxInt;
for(w=0;w<n;++w)
if(!S[w]&&D[w]<min)
{v=w; min=D[w]3}//选择一条当前的最短路径,终点为v
S[v]=true;
//r将v加入S
for(w=0;w<n;++w)//更新从v0出发到集合V-S上所有顶点的最短路径长度
if(!S[w]& &(D[v]+G.arcs[v][w]<D[w])){
D[w]=D[v]+G.arcs[v][w];//更新D[w]
Path [w]=v;//更改w的前驱为v
}//if
}//for
}//ShortestPath_DIJ
时间复杂度:
O(n
2)
顶点之间的最短路径
问题的提出
已知一个各边权值均大于0的带权有向图,对每一 对顶点vi≠vj,希望求出vi与vj之间的最短路径和最短路径长度。
解决思路
可以通过调用n次Dijkstra算法来完成,
具体方法是:每次以不同的顶点作为源点,调用狄克斯特拉算法求出从该源点到其余顶点的最短路径。重复n次就可求出每对顶点之间的最短路径。
由于迪杰斯特算法的时间复杂度为O(n2),所以这种算法的时间复杂度为O(n3)。
拓扑结构
有向无环图
用有向图来描述一个工程或系统的进行过程。
一个工程可以分为若干个子工程,只要完成了这些子工程(活动),就可以导致整个工程的完成。
AOV网(Activity On Vertices)——用顶点表示活动的网络 拓扑排序
AOE网(Activity On Edges)——用边表示活动的网络 关键路径
拓扑排序——AOV网
AOV网
用有向图表示一个工程。
用顶点表示活动,用有向边<Vi, Vj>表示活动Vi必须先于活动Vj进行。
在AOV网络中不能出现有向回路,即有向环。如果出现了有向环,则意味着某项活动应以自己作为先决条件。
对给定的AOV网络,必须先判断它是否存在有向环。
拓扑有序序列
将各个顶点(代表各个活动)排列成一个线性有序的序列,使得AOV网络中所有应存在的前驱和后继关系都能得到满足。
拓扑排序
构造AOV网络全部顶点的拓扑有序序列的运算就叫做拓扑排序。
结论
如果通过拓扑排序能将AOV网络的**所有顶点**都排入拓扑有序序列中,则该网络中必定不会出现有向环。
如果AOV网络中存在有向环,此AOV网络所代表的工程是不可行的。
过程
思想:
重复选择没有直接前驱的顶点
1、输入AOV网络。令n为顶点个数
2、选中一个没有直接前驱的顶点,输出
3、从图中删去该顶点,同时别去所有它发出的有向边
4、重复以上2、3步,直到:
全部顶点均已输出,拓扑有序序列形成,拓扑排序完成;
还有未输出的顶点,但已跳出处理循环。图中剩余顶点都有直接前驱,找不到没有前驱的顶点了。AOV网络中必定存在有向环。
步骤:
1、标入度
2、找入度为0的顶点,删掉,并删掉该点的出边
3、改入度,循环2
关键路径——AOE网
用边表示活动的网络(AOE ( Activity On Edges)网络)
前提
不存在有向环的带权有向图中
用有向边表示一个工程中的活动(Activity)
用边上权值表示活动持续时间(Duration)
应用
估算工程项目至少需要的完成时间((工期)?
为缩短完成工程所需的时间,应当加快哪些活动?
术语
源点
表示整个工程的开始点
汇点
表示整个工程的结束点
事件结点
时刻、里程碑
有向边
活动,权值定义为活动进行所需要的时间。
方向表示起始结点事件先发生,而终止结点事件才能发生。
源点到汇点:从源点到汇点的有向路径可能不止一条,路径的长度也可能不同。完成不同路径的活动所需的时间虽然不同,但只有各条路径上所有活动都完成了,整个工程才算完成。
关键路径
完成整个工程所需的时间取决于从源点到汇点的**最长**路径长度,即在这条路径上所有活动的持续时间之和。这条路径长度最长的路径就叫做关键路径(Critical Path)。
关键活动
要找出关键路径,必须找出关键活动,即不按期完成就会影响整个工程完成的活动。
关键路径上的所有活动都是关键活动。
因此,只要找到了关键活动,就可以找到关键路径。
事件Vj的最早发生时间(VE(j))
从源点v到本结点V的最长的路径。意味着事件最早能够发生的时刻。
事件Vj的最迟发生时间(VL(j))
是在保证汇点*Vn-1在VE(n-I)时刻完成的前提下,事件Vj*的允许的最迟开始时间。
不影响工程的如期完工,本结点事件必须发生的时刻。
活动ai的最早开始时间
AE((ai)= VE(j)
活动ai的起始事件点Vj的最早可能开始时间VE( j )
活动a,的最迟开始时间
AL(ai)=VL(k ) - dut(j , k )
活动ai的结束事件点Vk的最晚可能开始时间VL( j )-完成ai所需的时间
是指在不会引起时间延误的前提下,该活动允许的最迟开始时间。
时间余量
AL(a
i )-AE(a
i )
表示活动ai的最早可能开始时间和最迟允许开始时间的时间余量。
如何找到关键活动
AL(a
i )==AE(a
i )
表示活动(ai是没有时间余量的关键活动。
求每个活动的AL(ai )与AE(ai),以判别是否AL(ai )==AE(ai)
总结:
1、求出每个事件的VE->VL
2、求出每个活动的AE ->AL
3、if (AE==AL)得到关键活动
4、由关键活动确定关键路径
5、得出结论(编短工期的方法)
举例
关键路径:12579,12589
AOV和AOE总结
步骤1:先使用拓扑排序得到拓扑序列(工程安排)
步骤2:按照拓扑序列,求出关键路径,得到工程的工期
VE-> VL->AE ->AL
if ( AE= =AL)得到关键活动=》关键路径
得出结论:
① 对于一个工程,可以利用AOV网络分析工程在分解时是否合理(各个子工程间有否冲突);得到工程施工的调度顺序。
② 对于一个工程,在AOV的基础上,可以利用AOE网络分析工程的关键子工程(抓主要矛盾),计算工程的工期。
③在不改变关键路径的前提下,提高关键活动的功效,可以缩短工期。