ImageVerifierCode 换一换
格式:DOCX , 页数:13 ,大小:19.92KB ,
资源ID:10300033      下载积分:12 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10300033.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(图论算法.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

图论算法.docx

1、图论算法1.Dijkstra1) 适用条件&范围:a) 单源最短路径(从源点s到其它所有顶点v);b) 有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图)c) 所有边权非负(任取(i,j)E都有Wij0);2) 算法描述:a) 初始化:disv=maxint(vV,vs); diss=0; pres=s; S=s;b) For i:=1 to n1.取V-S中的一顶点u使得disu=mindisv|vV-S2.S=S+u3.For V-S中每个顶点v do Relax(u,v,Wu,v)c) 算法结束:disi为s到i的最短距离;prei为i的前驱节点3) 算法优化:

2、使用二叉堆(Binary Heap)来实现每步的DeleteMin(ExtractMin,即算法步骤b中第1步)操作,算法复杂度从O(V2)降到O(V+E)V)。推荐对稀疏图使用。 使用Fibonacci Heap(或其他Decrease操作O(1),DeleteMin操作O(logn)的数据结构)可以将复杂度降到O(E+VV);如果边权值均为不大于C的正整数,则使用Radix Heap可以达到O(E+VC)。但因为它们编程复杂度太高,不推荐在信息学竞赛中使用。注:程序使用二叉堆程序:program mtx_grp;const num=10; max=10000;typegrp=array1.

3、num,1.num of integer;rcd=set of 1.num;arr=array1.num of integer;arr2=array1.num of rcd;vari,j,w,m,n,e,k:integer;g:grp;visited:array1.num of boolean;path:arr2;dist,s:arr;procedure createmtx;var i,j,k:integer;begin for i:=1 to n do for j:=1 to n do gi,j:=max; for k:=1 to e do begin readln(i,j,w); gi,j

4、:=w; gj,i:=w; end;end;procedure print( g:grp); begin for i:=1 to n do begin for j:=1 to n do if gi,j=max then write(oo:4) else write(gi,j:4); writeln; end; end;procedure dijkstra(var dist:arr;var path:arr2;i:integer); begin e:=i; for j:=1 to n do begin if ji then sj:=0 else sj:=1; distj:=gi,j; if di

5、stjmax then pathj:=i+j else pathj:=; end; for k:=1 to n-2 do begin w:=max;m:=i; for j:=1 to n do if (sj=0) and (distjw) then begin m:=j;w:=distj;end; if mi then sm:=1 else exit; for j:=1 to n do if (sj=0) and (distm+gm,jdistj) then begin distj:=distm+gm,j; pathj:=pathm+j; end; end; for i:=1 to n do

6、if ie then begin for j:=1 to n do if j in pathi then write(j:3); writeln(w=:4,disti); end; end;begin assign(input,nodelst5.in); reset(input); readln(n,e); createmtx; writeln; readln(i); dijkstra(dist,path,i); writeln;end.2.Floyd-Warshall1) 适用范围:a) APSP(All Pairs Shortest Paths)b) 稠密图效果最佳c) 边权可正可负2)

7、算法描述:a) 初始化:disu,v=wu,vb) For k:=1 to nFor i:=1 to n For j:=1 to n If disi,jdisi,k+disk,j Then DisI,j:=disI,k+disk,j;c) 算法结束:dis即为所有点对的最短路径矩阵3) 算法小结:此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于执行|V|次Dijkstra算法。时间复杂度O(n3)。考虑下列变形:如(I,j)E则disI,j初始为1,else初始为0,这样的Floyd算法最后的最短路径矩阵即成为一个判断I,j是否有通路的矩阵。更简单的,我们可以把dis设成boole

8、an类型,则每次可以用“disI,j:=disI,jor(disI,kand disk,j)”来代替算法描述中的蓝色部分,可以更直观地得到I,j的连通情况。与Dijkstra算法类似地,算法中蓝色的部分可以加上对Pre数组的更新,不再赘述。4) 程序(直接写上的。或许有小错误)program floydvar i,j,k,n,m:longint;leng:array0.1001,0.1001of longint;beginreadln(n);for i:=1 to n dobegin for j:=1 to n doread(ai,j);readln;end; for k:=1 to n do

9、 for i:=1 to n do for j:=1 to n do if lengi,k+lengk,jlengi,j then begin lengi,j:=lengi,k+lengk,j; end;end.3.Prim1) 适用范围:a) MST(Minimum Spanning Tree,最小生成树)b) 无向图(有向图的是最小树形图)c) 多用于稠密图2) 算法描述:a) 初始化:disv=maxint(vV,vs); diss=0; pres=s; S=s;tot=0b) For i:=1 to n1.取顶点vV-S使得W(u,v)=minW(u,v)|uS,vV-S,(u,v)E

10、2.S=S+v;tot=tot+W(u,v);输出边(u,v)3.For V-S中每个顶点v do Relax(u,v,Wu,v)c) 算法结束:tot为MST的总权值注意:这里的Relax不同于求最短路径时的松弛操作。它的代码如下:procedure relax(u,v,w:integer); /松弛操作begin if wdisv then begin prev:=u; disv:=w; end;end; 可以看到,虽然不同,却也十分相似。3) 算法优化: 使用二叉堆(Binary Heap)来实现每步的DeleteMin(ExtractMin)操作算法复杂度从O(V2)降到O(V+E)V

11、)。推荐对稀疏图使用。 使用Fibonacci Heap可以将复杂度降到O(E+VV),但因为编程复杂度太高,不推荐在信息学竞赛中使用。 (不要问我为什么和Dijkstra一样观察我的prim和dijkstra程序,会发现基本上只有relax和输出不一样)程序:program mintree_prim(input);constmaxn=100;vara:array1.maxn,1.maxnof integer;b:array1.maxnof boolean;d:array1.maxnof integer;n,tot,i,j,k,min:integer;begin assign(input,pr

12、im.in); reset(input); tot:=0; readln(n); for i:=1 to n do bi:=true; b1:=false; for i:=1 to n do for j:=1 to n do begin read(ai,j); if ai,j=-1 then ai,j:=maxint; end; for i:=2 to n do di:=a1,i; for i:=1 to n-1 do begin min:=maxint; for j:=1 to n do if(bj)and(djak,j)then dj:=ak,j; end; writeln(tot); c

13、lose(input);end.4.Topological Sort(拓扑排序) 1) 适用条件&范围:a) AOV网(Activity On Vertex Network);b) 有向图;c) 作为某些算法的预处理过程(如DP)2) 算法描述:很简单的算法:每次挑选入度为0的顶点输出(不计次序)。如果最后发现输出的顶点数小于|V|,则表明有回路存在3) 算法实现:a) 数据结构: adj:邻接表;有4个域u,v,w,nextindgri:顶点i的入度;stack:栈b) 初始化:top=0 (栈顶指针)c) 将初始状态所有入度为0的顶点压栈d) I=0 (计数器)e) While 栈非空(t

14、op0) do i. 顶点v出栈;输出v;计数器增1; ii. For 与v邻接的顶点u do1. dec(indgru);2. If indgru=0 then 顶点u入栈f) EXIT(I=|V|)简单&高效&实用的算法。上述实现方法复杂度O(V+E)4) 程序:有向图的拓扑排序每次找入度为0的顶点入栈成功返回true,有环返回false总复杂度O(n+e)const maxn=100;type link=node; node=record v,w :integer; next :link; end; arr=array1.maxnof 1.maxn;var adj :array1.max

15、nof link; /邻接表 tsort,indgr :arr; /拓扑序列;入度 n,s,i :integer;procedure init;var u,v,w :integer; p :link;begin assign(input,g.in);reset(input); readln(n,s); while not eof do begin readln(u,v,w); new(p); p.v:=v;p.w:=w; p.next:=adju; adju:=p; inc(indgrv) end;end;function toposort(indgr:arr):boolean;var i,t

16、op :integer; p :link; stack :array1.maxnof integer;begin top:=0; for i:=1 to n do if indgri=0 then begin inc(top); stacktop:=i end; i:=0; while top0 do begin inc(i); tsorti:=stacktop; dec(top); p:=adjtsorti; while pnil do begin dec(indgrp.v); if indgrp.v=0 then begin inc(top); stacktop:=p.v end; p:=

17、p.next; end; end; exit(i=n)end;=main=begin init; if toposort(indgr) then for i:=1 to n do write(tsorti, ) else writeln(A circle found)end.5.Kruskal 1) 适用范围:a) MST(Minimum Spanning Tree,最小生成树)b) 无向图(有向图的是最小树形图)c) 多用于稀疏图d) 边已经按权值排好序给出2) 算法描述:基本思想:每次选不属于同一连通分量(保证无圈)且边权值最小的2个顶点,将边加入MST,并将所在的2个连通分量合并,直到只

18、剩一个连通分量3) 算法实现:a) 将边按非降序排列(Quicksort,O(EE)b) While 合并次数少于|V|-1 i. 取一条边(u,v)(因为已经排序,所以必为最小) ii. If u,v不属于同一连通分量 then1) 合并u,v所在的连通分量2) 输出边(u,v)3) 合并次数增1;tot=tot+W(u,v)c) 算法结束:tot为MST的总权值4) 分析总结:检查2个顶点是否在同一连通分量可以使用并查集实现(连通分量看作等价类)。我们可以看到,算法主要耗时在将边排序上。如果边已经按照权值顺序给出,那太棒了另外一种可以想到的实现方法为:O(n)时间关于边权建二叉小根堆;每次

19、挑选符合条件的边时使用堆的DelMin操作。这种方法比用Qsort预排序的方法稍微快一些,编程复杂度基本一样。附程序。另外,如果边权有一定限制,即=某常数c,则可以使用线性时间排序以获得更好的时间效率。5) 程序:program kruskal;type arr=array0.100,1.3of longint;varn,m,i,j,k,min,vt:longint;s,t:array0.100of longint;g:arr;procedure heap(var r:arr;nn,ii:longint);var fr,en,i,j,x:longint;begini:=ii;x:=ri,3;f

20、r:=ri,1;en:=ri,2;j:=2*ii;while j=nn dobeginif (jnn)and(rj,3rj+1,3) then inc(j);if xrj,3 then begin ri,3:=rj,3;ri,2:=rj,2;ri,1:=rj,1; i:=j;j:=2*i; end else j:=nn+1; end; ri,3:=x; ri,2:=en;ri,1:=fr;end;beginassign(input,kruskal.in);reset(input); readln(n,m); for i:=1 to m do readln(gi,1,gi,2,gi,3); fo

21、r i:=m div 2 downto 1 do heap(g,m,i); for i:= m downto 2 do begin k:=gi,1;gi,1:=g1,1;g1,1:=k; k:=gi,2;gi,2:=g1,2;g1,2:=k; k:=gi,3;gi,3:=g1,3;g1,3:=k; heap(g,i-1,1); end; fillchar(s,sizeof(s),0); fillchar(t,sizeof(t),0); vt:=0; for i:=1 to n-1 do begin min:=maxlongint; k:=0; for j:=1 to m do if sj=0 then if(tgj,1=0)xor(tgj,2=0)or(i=1)then if gj,3,gi,2); end; writeln(vt);end.

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1