收藏 分享(赏)

经典图论算法.doc

上传人:buyk185 文档编号:6071950 上传时间:2019-03-26 格式:DOC 页数:23 大小:2.85MB
下载 相关 举报
经典图论算法.doc_第1页
第1页 / 共23页
经典图论算法.doc_第2页
第2页 / 共23页
经典图论算法.doc_第3页
第3页 / 共23页
经典图论算法.doc_第4页
第4页 / 共23页
经典图论算法.doc_第5页
第5页 / 共23页
点击查看更多>>
资源描述

1、第 1 页 共 23 页图论中的常用经典算法第一节 最小生成树算法一、生成树的概念若图是连通的无向图或强连通的有向图,则从其中任一个顶点出发调用一次 bfs 或 dfs 后便可以系统地访问图中所有顶点;若图是有根的有向图,则从根出发通过调用一次 dfs 或 bfs 亦可系统地访问所有顶点。在这种情况下,图中所有顶点加上遍历过程中经过的边所构成的子图称为原图的生成树。对于不连通的无向图和不是强连通的有向图,若有根或者从根外的任意顶点出发,调用一次bfs 或 dfs 后不能系统地访问所有顶点,而只能得到以出发点为根的连通分支(或强连通分支)的生成树。要访问其它顶点则还需要从没有访问过的顶点中找一个

2、顶点作为起始点,再次调用bfs 或 dfs,这样得到的是生成森林。由此可以看出,一个图的生成树是不唯一的,不同的搜索方法可以得到不同的生成树,即使是同一种搜索方法,出发点不同亦可导致不同的生成树。如下图:但不管如何,我们都可以证明:具有 n 个顶点的带权连通图,其对应的生成树有 n-1 条边。二、求图的最小生成树算法严格来说,如果图 G=(V,E)是一个连通的无向图,则把它的全部顶点 V 和一部分边 E构成一个子图 G,即 G=(V, E) ,且边集 E能将图中所有顶点连通又不形成回路,则称子图G是图 G 的一棵生成树。对于加权连通图,生成树的权即为生成树中所有边上的权值总和,权值最小的生成树

3、称为图的最小生成树。求图的最小生成树具有很高的实际应用价值,比如下面的这个例题。例 1、城市公交网问题描述有一张城市地图,图中的顶点为城市,无向边代表两个城市间的连通关系,边上的权为在这两个城市之间修建高速公路的造价,研究后发现,这个地图有一个特点,即任一对城市都是连通的。现在的问题是,要修建若干高速公路把所有城市联系起来,问如何设计可使得工程的总造价最少。输入 第 2 页 共 23 页n(城市数,1k Then Begin t:=elistk;elistk:=elistm;elistm:=t;End;把权值最小的边调到第 k 个单元j:=elistk.endv; j 为新加入的顶点For i

4、:=k+1 To n-1 Do 修改未加入的边集Begin s:=elisti.endv; w:=gj,s;If wm2 Then Begin 找到的 elist 第 j 条边满足条件,作为第 i 条边保留Ci:=j;i:=i+1;sm1:=sm1+sm2;合并两个集合sm2:= ; 另一集合置空End;j:=j+1; 取下条边,继续判断End; 输出最小生成树的各边:elistCi3、总结以上两个算法的时间复杂度均为 O(n*n) 。参考程序见 Prim.pas 和 Kruskal.pas。请大家用以上两种算法完成例 1。三、应用举例例 2、最优布线问题(wire.pas,wire.exe)

5、问题描述学校有 n 台计算机,为了方便数据传输,现要将它们用数据线连接起来。两台计算机被连接是指它们时间有数据线连接。由于计算机所处的位置不同,因此不同的两台计算机的连接费用往往是不同的。当然,如果将任意两台计算机都用数据线连接,费用将是相当庞大的。为了节省费用,我们采用数据的间接传输手段,即一台计算机可以间接的通过若干台计算机(作为中转)来实现与另一台计算机的连接。现在由你负责连接这些计算机,你的任务是使任意两台计算机都连通(不管是直接的或间接的) 。输入格式 输入文件 wire.in,第一行为整数 n(2maxint)and(ht+gt,ij) then gi,j:=maxint;end;

6、bfs;for i:=2 to n dowriteln(From 1 To ,i, Weigh ,hi);close(input);end.五、迭代法该算法的中心思想是:任意两点 i,j 间的最短距离(记为 Dij)会等于从 i 点出发到达 j 点的以任一点为中转点的所有可能的方案中,距离最短的一个。即:Dij = min Dij , Dik+Dkj ,1Dk+gk,j then begin Dj:= Dk+gk,j; c:=true; end;Until not c;这种算法是产生这样一个过程:不断地求一个数字最短距离矩阵中的数据的值,而当所有数据都已经不能再变化时,就已经达到了目标的平衡状

7、态,这时最短距离矩阵中的值就是对应的两点间的最短距离。这个算法实现的程序如下:const maxn=100;maxint=maxlongint div 4;第 10 页 共 23 页var D:array1maxn of longint;g:array1maxn,1maxn of longint;n,i,j,k:longint;c:boolean;beginassign(input,data.in);reset(input);read(n);for i:=1 to n dofor j:=1 to n dobeginread(gi,j);if (gi,jj) then gi,j:=maxint;

8、end;for i:=1 to n do Di:=g1,i;repeatc:=false;for j:=1 to n dofor k:=1 to n do k 是中转点if DjDk+gk,j thenbeginDj:=Dk+gk,j;c:=true;end;until not c;for i:=2 to n dowriteln(From 1 To ,i, Weigh ,Di);close(input);end.六、动态规划动态规划算法已经成为了许多难题的首选算法。某些最短路径问题也可以用动态规划来解决,通常这类最短路径问题所对应的图必须是有向无回路图。因为如果存在回路,动态规划的无后效性就无

9、法满足。我们知道,动态规划算法与递归算法的不同之处在于它们的算法表达式:递归:类似 f(n)=x1*f(n-1)+x2*f(n-2),即可以找到一个确定的关系的表达式;动态规划:类似 f(n)=min(f(n-1)+x1,f(n-2)+x2),即我们无法找到确定关系的表达式,只能找到这样一个不确定关系的表达式,f(n)的值是动态的,随着 f(n-1),f(n-2)等值的改变而确定跟谁相关。为了给问题划分阶段,必须对图进行一次拓扑排序(见下一节内容) ,然后按照拓扑排序的结果来动态规划。譬如,有如下两个有向图:3BD C E A9852143BD C E A985214第 11 页 共 23 页

10、右图因为存在回路而不能用动态规划。而左图是无回路的,所以可以用动态规划解决。对左图拓扑排序,得到的序列是 A、B、D、C、E。设 F(E)表示从 A 到 E 的最短路径长度,然后按照拓扑序列的先后顺序进行动态规划:F(A)=0F(B)=min F(A) +3=3F(D)=min F(A)+8, F(B)+2 =5F(C)=min F(B)+9, F(D)+5 =10F(E)=min F(D)+1, F(C)+4 =6总的式子是:F(i)=min F(k)+dis(i,k) ,k 与 i 必须相连,且在拓扑序列中,k 在 i 之前。这个算法的参考程序如下:const maxn=100;maxin

11、t=maxlongint div 4;var g:array1maxn,1maxn of longint;有向图的邻接矩阵pre:array1maxn of longint; prei记录结点 i 的入度tp:array1maxn of longint; 拓扑排序得到的序列s:array1maxn of longint; 记录最短路径长度n,i,j,k:longint;beginassign(input,data.in);reset(input);read(n);fillchar(pre,sizeof(pre),0);for i:=1 to n dofor j:=1 to n dobeginr

12、ead(gi,j);if gi,j0 thenprej:=prej+1; 如果存在一条有向边 ij,就把 j 的入度加 1end;for i:=1 to n do 拓扑排序beginj:=1;while (prej0 thenprek:=prek-1;end;filldword(s,sizeof(s)div 4,maxint); s 数组中的单元初始化为 maxints1:=0; 默认起点是 1 号结点第 12 页 共 23 页for i:=2 to n do 动态规划for j:=1 to i doif (gtpj,tpi0)and(stpj+gtpj,tpij)and(gi,j=0) th

13、en gi,j:=maxint;end;fillchar(mark,sizeof(mark),false); mark 初始化为 falsemark1:=true; 将起点标志为已扩展for i:=1 to n do si:=g1,i; s 数组初始化repeatk:=0;for j:=1 to n do 挑选离原点最近的点if (not markj)and(k=0)or(sksj) thenk:=j;if k0 Do 栈不空Beginj:=top; 取一个入度为 0 的顶点序号top:=dig.adjtop.id; 出栈、删除当前处理的顶点、指向下个入度为 0 的顶点Write(dig.ad

14、jtop.v); 输出顶点序号m:=m+1;p:=dig.adjj.link; 指向 Vj邻接表的第一个邻接点While pB,BD,FD。士兵的身高关系如图所示:对应的排队方案有三个:AFBD、FABD、ABFD。输入:(soldier.in)第一行:一个整数 k第二至第 k+1 行:每行两个大写字母(中间和末尾都没有空格) ,代表两个士兵,且第一个士兵高度大于第二个士兵。输出:(soldier.out)一个只包含大写字母的字符序列,表示排队方案(只要一种方案即可) 。输入样例:(soldier.in)3ABBDFD输出样例:(soldier.out)AFBD问题分析:士兵的身高关系对应一张

15、有向图,图中的顶点对应一个士兵,有向边表示士兵 i 高于士兵 j。我们按照从高到矮将士兵排出一个线形的顺序关系,即为对有向图的顶点进行拓扑排序。参考程序:program soldier;var g:arrayAZ,AZ of 01; 图的邻接矩阵d:arrayAZ of longint; 记录各顶点的入度s:arrayAZ of boolean; 用来记录出现过的士兵名ans:string;ch,i:char;procedure readata; 读入,构图var i,j,k:longint;a,b:char;beginfillchar(g,sizeof(g),0); g、d、s 初始化第 2

16、0 页 共 23 页fillchar(d,sizeof(d),0);fillchar(s,sizeof(s),false);readln(k); 读入边的条数for i:=1 to k dobeginreadln(a,b);ga,b:=1; 构造有向边 abdb:=db+1; 将 b 的入度加 1sa:=true; 将 a、b 标记为出现过sb:=true;end;end;begin mainassign(input,soldier.in);reset(input);assign(output,soldier.out);rewrite(output);readata;ans:=; 拓扑排序re

17、peatch:=A;while (chZ;writeln(ans);close(input);close(output);end.第四节 关键路径算法利用 AOV 网络,对其进行拓扑排序能对工程中活动的先后顺序作出安排。但一个活动的完成总需要一定的时间,为了能估算出某个活动的开始时间,找出那些影响工程完成时间的最主要的活动,我们可以利用带权的有向网,图中的边表示活动,边上的权表示完成该活动所需要的时间,一条边的两个顶点分别表示活动的开始事件和结束事件,这种用边表示活动的网络,称为“AOE网” 。其中,有两个特殊的顶点(事件) ,分别称为源点和汇点,源点表示整个工程的开始,通常令第一个事件(事件

18、 1)作为源点,它只有出边没有入边;汇点表示整个工程的结束,通常令最后一个事件(事件 n)作为汇点,它只有入边没有出边;其余事件的编号为 2 到 n-1。第 21 页 共 23 页在实际应用中,AOE 网应该是没有回路的,并且存在唯一的入度为 0 的源点和唯一的出度为 0 的汇点。下图表示一个具有 12 个活动的 AOE 网。图中有 8 个顶点,分别表示事件 0 到 7,其中,0 表示开始事件,7 表示结束事件,边上的权表示完成该活动所需要的时间。AOE 网络要研究的问题是完成整个工程至少需要多少时间?哪些活动是影响工程进度的关键?下面先讨论一个事件的最早发生时间和一个活动的最早开始时间。如下

19、图,事件 Vj必须在它的所有入边活动 eik(1kn)都完成后才能发生。活动 eik(1kn)的最早开始时间是与它对应的起点事件 Vik的最早发生时间。所有以事件 Vj为起点事件的出边活动 ejk(1km)的最早开始时间都等于事件 Vj的最早发生时间。所以,我们可以从源点出发按照上述方法,求出所有事件的最早发生时间。设数组 earliest1n表示所有事件的最早发生时间,则我们可以按照拓扑顺序依次计算出earliestk:earliest1=0earliestk=maxearliestj+dutj,k (其中,事件 j 是事件 k 的直接前驱事件,dutj,k表示边上的权)对于上图,用上述方法

20、求 earliest07的过程如下:earliest0=0earliest1=earliest0+dut0,1=0+6=6earliest2=earliest0+dut0,2=0+7=7earliest4=maxearliest1+dut1,4,earliest2+dut2,4=max6+5,7+4=11earliest3=maxearliest1+dut1,3,earliest4+dut4,3=max6+3,11+3=14earliest5=maxearliest3+dut3,5,earliest4+dut4,5=max14+2,11+4=16earliest6=earliest4+dut4

21、,6=11+3=14earliest7=maxearliest3+dut3,7,earliest5+dut5,7, earliest6+dut6,7=max14+5,16+2,14+4=19第 22 页 共 23 页最后得到的 earliest7就是汇点的最早发生时间,从而可知整个工程至少需要 19 天完成。但是,在不影响整个工程按时完成的前提下,一些事件可以不在最早发生时间发生,而向后推迟一段时间,我们把事件最晚必须发生的时间称为该事件的最迟发生时间。同样,有些活动也可以推迟一段时间完成而不影响整个工程的完成,我们把活动最晚必须开始的时间称为该活动的最迟开始时间。一个事件在最迟发生时间内仍没

22、发生,或一个活动在最迟开始时间内仍没开始,则必然会影响整个工程的按时完成。事件 Vj的最迟发生时间应该为:它的所有直接后继事件Vjk(1km)的最迟发生时间减去相应边上的权(活动 ejk需要时间) ,取其中的最小值。且汇点的最迟发生时间就是它的最早发生时间,再按照逆拓扑顺序依次计算出所有事件的最迟发生时间,设用数组 lastest1n表示,即:lastestn=earliestnlastestj=minlastestk-dutj,k (其中,事件 k 是事件 j 的直接后继事件,dutj,k表示边上的权)对于上图,用上述方法求 lastest 07的过程如下:lastest7=earliest

23、7=19lastest6=lastest7-dut6,7=19-4=15lastest5=lastest7-dut5,7=19-2=17lastest3=minlastest5-dut3,5,lastest7-dut3,7=min17-2,19-5=14lastest4=minlastest3-dut4,3,lastest5-dut4,5, lastest6-dut4,6=min14-3,17-4,15-3=11lastest2=lastest4-dut2,4=11-4=7lastest1=minlastest3-dut1,3,lastest4-dut1,4=min14-3,11-5=6las

24、test0=minlastest1-dut0,1,lastest2-dut0,2=min6-6,7-7=0计算好每个事件的最早和最迟发生时间后,我们可以很容易地算出每个活动的最早和最迟开始时间,假设分别用 actearliest 和 actlastest 数组表示,设活动 i 的两端事件分别为事件 j 和事件 k,如下所示:活动 i事件 j 事件 k则:actearliesti=earliestjactlastesti=lastestk-dutj,k对于上图,用上述方法求得所有活动的最早和最迟开始时间如下表:活动 最早 0 0 6 6 7 14 14 11 11 11 16 14最迟 0 0

25、11 6 7 15 14 11 13 12 17 15余量 0 0 5 0 0 1 0 0 2 1 1 1上表中的余量(称为开始时间余量)是该活动的最迟开始时间减去最早开始时间,余量不等第 23 页 共 23 页于 0 的活动表示该活动不一定要在最早开始时间时就进行,可以拖延一定的余量时间再进行,也不会影响整个工程的完成。而余量等于 0 的活动必须在最早开始时间时进行,而且在规定的工期内完成,否则将影响整个工程的完成。我们把开始时间余量为 0 的活动称为“关键活动” ,由关键活动所形成的从源点到汇点的每一条路径称为“关键路径” 。上图所示的 AOE 网的关键路径如下图所示。细心的读者可能已经发现,其实关键路径就是从源点到汇点具有最大路径长度的那些路径。这很容易理解,因为整个工程的工期就是按照最长路径计算出来的。很显然,要想缩短整个工程的工期,就应该想法设法去缩短关键活动的持续时间。读者可以根据上面的思想编程求出 AOE 网的关键路径。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 学术论文 > 大学论文

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报