Johnson 全源最短路径算法.docx
- 文档编号:12659566
- 上传时间:2023-04-21
- 格式:DOCX
- 页数:17
- 大小:19.27KB
Johnson 全源最短路径算法.docx
《Johnson 全源最短路径算法.docx》由会员分享,可在线阅读,更多相关《Johnson 全源最短路径算法.docx(17页珍藏版)》请在冰豆网上搜索。
Johnson全源最短路径算法
Johnson全源最短路径算法
解决单源最短路径问题(SingleSourceShortestPathsProblem)的算法包括:
Dijkstra单源最短路径算法:
时间复杂度为O(E+VlogV),要求权值非负;
Bellman-Ford单源最短路径算法:
时间复杂度为O(VE),适用于带负权值情况;
对于全源最短路径问题(All-PairsShortestPathsProblem),可以认为是单源最短路径问题的推广,即分别以每个顶点作为源顶点并求其至其它顶点的最短距离。
例如,对每个顶点应用Bellman-Ford算法,则可得到所有顶点间的最短路径的运行时间为O(V2E),由于图中顶点都是连通的,而边的数量可能会比顶点更多,这个时间没有比Floyd-Warshall全源最短路径算法O(V3)更优。
那么,再试下对每个顶点应用Dijkstra算法,则可得到所有顶点间的最短路径的运行时间为O(VE+V2logV),看起来优于Floyd-Warshall算法的O(V3),所以看起来使用基于Dijkstra算法的改进方案好像更好,但问题是Dijkstra算法要求图中所有边的权值非负,不适合通用的情况。
在1977年,DonaldB.Johnson提出了对所有边的权值进行"re-weight"的算法,使得边的权值非负,进而可以使用Dijkstra算法进行最短路径的计算。
我们先自己思考下如何进行"re-weight"操作,比如,简单地对每条边的权值加上一个较大的正数,使其非负,是否可行?
111
s-----a-----b-----c
\/
\/
\______/
4
比如上面的图中,共4条边,权值分别为1,1,1,4。
当前s-->c的最短路径是{s-a,a-b,b-c}即1+1+1=3。
而如果将所有边的权值加1,则最短路径就会变成{s-c}的5,因为2+2+2=6,实际上导致了最短路径的变化,显然是错误的。
那么,Johnson算法是如何对边的权值进行"re-weight"的呢?
以下面的图G为例,有4个顶点和5条边。
首先,新增一个源顶点4,并使其与所有顶点连通,新边赋权值为0,如下图所示。
使用Bellman-Ford算法计算新的顶点到所有其它顶点的最短路径,则从4至{0,1,2,3}的最短路径分别是{0,-5,-1,0}。
即有h[]={0,-5,-1,0}。
当得到这个h[]信息后,将新增的顶点4移除,然后使用如下公式对所有边的权值进行"re-weight":
w(u,v)=w(u,v)+(h[u]-h[v]).
则可得到下图中的结果:
此时,所有边的权值已经被"re-weight"为非负。
此时,就可以利用Dijkstra算法对每个顶点分别进行最短路径的计算了。
Johnson算法描述如下:
给定图G=(V,E),增加一个新的顶点s,使s指向图G中的所有顶点都建立连接,设新的图为G’;
对图G’中顶点s使用Bellman-Ford算法计算单源最短路径,得到结果h[]={h[0],h[1],..h[V-1]};
对原图G中的所有边进行"re-weight",即对于每个边(u,v),其新的权值为w(u,v)+(h[u]-h[v]);
移除新增的顶点s,对每个顶点运行Dijkstra算法求得最短路径;
Johnson算法的运行时间为O(V2logV+VE)。
Johnson算法伪码实现如下:
Johnson算法C#代码实现如下:
复制代码
1usingSystem;
2usingSystem.Collections.Generic;
3usingSystem.Linq;
4
5namespaceGraphAlgorithmTesting
6{
7classProgram
8{
9staticvoidMain(string[]args)
10{
11//buildadirectedandnegativeweightedgraph
12GraphdirectedGraph1=newGraph(5);
13directedGraph1.AddEdge(0,1,-1);
14directedGraph1.AddEdge(0,2,4);
15directedGraph1.AddEdge(1,2,3);
16directedGraph1.AddEdge(1,3,2);
17directedGraph1.AddEdge(1,4,2);
18directedGraph1.AddEdge(3,2,5);
19directedGraph1.AddEdge(3,1,1);
20directedGraph1.AddEdge(4,3,-3);
21
22Console.WriteLine();
23Console.WriteLine("GraphVertexCount:
{0}",directedGraph1.VertexCount);
24Console.WriteLine("GraphEdgeCount:
{0}",directedGraph1.EdgeCount);
25Console.WriteLine();
26
27int[,]distSet1=directedGraph1.Johnsons();
28PrintSolution(directedGraph1,distSet1);
29
30//buildadirectedandpositiveweightedgraph
31GraphdirectedGraph2=newGraph(4);
32directedGraph2.AddEdge(0,1,5);
33directedGraph2.AddEdge(0,3,10);
34directedGraph2.AddEdge(1,2,3);
35directedGraph2.AddEdge(2,3,1);
36
37Console.WriteLine();
38Console.WriteLine("GraphVertexCount:
{0}",directedGraph2.VertexCount);
39Console.WriteLine("GraphEdgeCount:
{0}",directedGraph2.EdgeCount);
40Console.WriteLine();
41
42int[,]distSet2=directedGraph2.Johnsons();
43PrintSolution(directedGraph2,distSet2);
44
45Console.ReadKey();
46}
47
48privatestaticvoidPrintSolution(Graphg,int[,]distSet)
49{
50Console.Write("\t");
51for(inti=0;i 52{ 53Console.Write(i+"\t"); 54} 55Console.WriteLine(); 56Console.Write("\t"); 57for(inti=0;i 58{ 59Console.Write("-"+"\t"); 60} 61Console.WriteLine(); 62for(inti=0;i 63{ 64Console.Write(i+"|\t"); 65for(intj=0;j 66{ 67if(distSet[i,j]==int.MaxValue) 68{ 69Console.Write("INF"+"\t"); 70} 71else 72{ 73Console.Write(distSet[i,j]+"\t"); 74} 75} 76Console.WriteLine(); 77} 78} 79 80classEdge 81{ 82publicEdge(intbegin,intend,intweight) 83{ 84this.Begin=begin; 85this.End=end; 86this.Weight=weight; 87} 88 89publicintBegin{get;privateset;} 90publicintEnd{get;privateset;} 91publicintWeight{get;privateset;} 92 93publicvoidReweight(intnewWeight) 94{ 95this.Weight=newWeight; 96} 97 98publicoverridestringToString() 99{ 100returnstring.Format( 101"Begin[{0}],End[{1}],Weight[{2}]", 102Begin,End,Weight); 103} 104} 105 106classGraph 107{ 108privateDictionary 109=newDictionary 110 111publicGraph(intvertexCount) 112{ 113this.VertexCount=vertexCount; 114} 115 116publicintVertexCount{get;privateset;} 117 118publicintEdgeCount 119{ 120get 121{ 122return_adjacentEdges.Values.SelectMany(e=>e).Count(); 123} 124} 125 126publicvoidAddEdge(intbegin,intend,intweight) 127{ 128if(! _adjacentEdges.ContainsKey(begin)) 129{ 130varedges=newList 131_adjacentEdges.Add(begin,edges); 132} 133 134_adjacentEdges[begin].Add(newEdge(begin,end,weight)); 135} 136 137publicvoidAddEdge(Edgeedge) 138{ 139AddEdge(edge.Begin,edge.End,edge.Weight); 140} 141 142publicvoidAddEdges(IEnumerable 143{ 144foreach(varedgeinedges) 145{ 146AddEdge(edge); 147} 148} 149 150publicIEnumerable 151{ 152return_adjacentEdges.Values.SelectMany(e=>e); 153} 154 155publicint[,]Johnsons() 156{ 157//distSet[,]willbetheoutputmatrixthatwillfinallyhavetheshortest 158//distancesbetweeneverypairofvertices 159int[,]distSet=newint[VertexCount,VertexCount]; 160 161for(inti=0;i 162{ 163for(intj=0;j 164{ 165distSet[i,j]=int.MaxValue; 166} 167} 168for(inti=0;i 169{ 170distSet[i,i]=0; 171} 172 173//step1: addnewvertexsandconnecttoallvertices 174Graphg=newGraph(this.VertexCount+1); 175g.AddEdges(this.GetAllEdges()); 176 177ints=this.VertexCount; 178for(inti=0;i 179{ 180g.AddEdge(s,i,0); 181} 182 183//step2: useBellman-Fordtoevaluateshortestpathsfroms 184int[]h=g.BellmanFord(s); 185 186//step3: re-weightingedgesoftheoriginalgraph 187//w(u,v)=w(u,v)+(h[u]-h[v]) 188foreach(varedgeinthis.GetAllEdges()) 189{ 190edge.Reweight(edge.Weight+(h[edge.Begin]-h[edge.End])); 191} 192 193//step4: useDijkstraforeachedges 194for(intbegin=0;begin 195{ 196int[]dist=this.Dijkstra(begin); 197for(intend=0;end 198{ 199if(dist[end]! =int.MaxValue) 200{ 201distSet[begin,end]=dist[end]-(h[begin]-h[end]); 202} 203} 204} 205 206returndistSet; 207} 208 209publicint[,]FloydWarshell() 210{ 211/*distSet[,]willbetheoutputmatrixthatwillfinallyhavetheshortest 212distancesbetweeneverypairofvertices*/ 213int[,]distSet=newint[VertexCount,VertexCount]; 214 215for(inti=0;i 216{ 217for(intj=0;j 218{ 219distSet[i,j]=int.MaxValue; 220} 221} 222for(inti=0;i 223{ 224distSet[i,i]=0; 225} 226 227/*Initializethesolutionmatrixsameasinputgraphmatrix.Or 228wecansaytheinitialvaluesofshortestdistancesarebased 229onshortestpathsconsideringnointermediatevertex.*/ 230foreach(varedgein_adjacentEdges.Values.SelectMany(e=>e)) 231{ 232distSet[edge.Begin,edge.End]=edge.Weight; 233} 234 235/*Addallverticesonebyonetothesetofintermediatevertices. 236--->Beforestartofaiteration,wehaveshortestdistancesbetweenall 237pairsofverticessuchthattheshortestdistancesconsideronlythe 238verticesinset{0,1,2,..k-1}asintermediatevertices. 239--->Aftertheendofaiteration,vertexno.kisaddedtothesetof 240intermediateverticesandthesetbecomes{0,1,2,..k}*/ 241for(intk=0;k 242{ 243//Pickallverticesassourceonebyone 244for(inti=0;i 245{ 246//Pickallverticesasdestinationfortheabovepickedsource 247for(intj=0;j 248{ 249//Ifvertexkisontheshortestpathfrom 250//itoj,thenupdatethevalueofdistSet[i,j] 251if(distSet[i,k]! =int.MaxValue 252&&distSet[k,j]! =int.MaxValue 253&&distSet[i,k]+distSet[k,j] 254{ 255distSet[i,j]=distSet[i,k]+distSet[k,j]; 256} 257} 258} 259} 260 261returndistSet; 262} 263 264publicint[]BellmanFord(intsource) 265{ 266//distSet[i]willholdtheshortestdistancefromsourcetoi 267int[]distSet=newint[VertexCount]; 268 269//Step1: InitializedistancesfromsourcetoallotherverticesasINFINITE 270for(inti=0;i 271{ 272distSet[i]=int.MaxValue; 273} 274distSet[source]=0; 275 276//Step2: Relaxalledges|V|-1times.Asimpleshortestpathfromsource 277//toanyothervertexcanhaveat-most|V|-1edges 278for(inti=1;i<=VertexCount-1;i++) 279{ 280foreach(varedgein_adjacentEdges.Values.SelectMany(e=>e)) 281{ 282intu=edge.Begin; 283intv=edge.End; 284intweight=edge.Weight; 285 286if(distSet[u]! =int.MaxValue 287&&distSet[u]+weight 288{ 289distSet[v]=distSet[u]+weight; 290} 291} 292} 293 294//Step3: checkfornegative-weightcycles.Theabovestepguarantees 295//shortestdistancesifgraphdoesn'tcontainnegativeweightcycle. 296//Ifwegetashorterpath,thenthereisacycle. 297foreach(varedgein_adjacentEdges.Values.SelectMany(e=>e)) 298{ 299intu=edge.Begin; 300intv
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Johnson 全源最短路径算法 全源最短 路径 算法