Graph Theory (iv) ------ single-source shortest path of a non-negative weighted directed graph, Dijkstra algorithm, single-source dijkstra
Dijkstra algorithm solves the single-source shortest path with weights on Directed Graph G = (V, E), but requires that the weights of all edges be non-negative.
Dijkstra is a good example of greedy algorithms. Set a vertex set S. the weights of the final shortest path from the source point s to the vertex S in the set are determined. The algorithm repeatedly selects vertex u with Shortest Path estimation, and adds u to S
All outbound edges. If the shortest path of vertex v can be improved through u, the estimated value of vertex v is updated.
For example, if u is the Source Vertex, all vertices are added to the priority queue.
In the queue, the minimum value is u (the value is 0). In the u output queue, the outbound edges of u are relaxed (x, v, w), and the minimum value of the queue is x.
Add the column x to S to relax the outbound edge of x (v, y, w). The value of w needs to be updated (4 <5), and the minimum value of the queue is v.
Add "v" to "S", and relax "w". Because x is already in "S", no relaxation is performed. The minimum value in the queue is y.
Add y to columns and y to S, Relax y's outdegree (w, z), update w value (3 <4), and the minimum queue value is w.
Add w out of columns to S, relax w out edge (z), and the minimum queue value is z.
Add z to S. Loosen the outbound edge of z (none). The queue is empty and the algorithm ends.
The running time of the Dijkstra algorithm depends on the specific implementation of the Minimum priority queue. If an array is used to calculate the minimum value, the running time is O (V2 + E) = O (V2 ).
If the graph is sparse, E = o (V2/lgV), and if it is implemented using a binary least heap, It is O (V + E) lgV ).
If implemented using the Fibonacci heap, it can be upgraded to O (VlgV + E ).
import sysclass Vertex(object): def __init__(self,key): self.id=key self.adj={} def addNeighbor(self,nbr,weight=0): self.adj[nbr]=weight def getNeighbors(self): return self.adj.keys() def getId(self): return self.id def getWeight(self,key): return self.adj[key]class Graph(object): def __init__(self): self.vertexlist={} self.size=0 def addVertex(self,key): vertex=Vertex(key) self.vertexlist[key]=vertex self.size+=1 return vertex def getVertex(self,key): return self.vertexlist.get(key) def __contains__(self,key): if key in self.vertexlist: return True else: return False def addEdge(self,f,t,weight=0): if f not in self.vertexlist: self.addVertex(f) if t not in self.vertexlist: self.addVertex(t) self.vertexlist[f].addNeighbor(self.vertexlist[t],weight) def getVertices(self): return self.vertexlist.keys() def __iter__(self): return iter(self.vertexlist.values())def Dijkstra(G,s): path={} vertexlist=[] for v in G: vertexlist.append(v) path[v]=sys.maxsize path[s]=0 queue=PriorityQueue(path) queue.buildHeap(vertexlist) while queue.size>0: vertex=queue.delMin() for v in vertex.getNeighbors(): newpath=path[vertex]+vertex.getWeight(v) if newpath<path[v]: path[v]=newpath queue.perUp(v) return path class PriorityQueue(object): def __init__(self,path): self.path=path self.queue=[] self.size=0 def buildHeap(self,alist): self.queue=alist self.size=len(alist) for i in xrange(self.size/2-1,0,-1): self._perDown(i) def delMin(self): self.queue[0],self.queue[-1]=self.queue[-1],self.queue[0] minvertex=self.queue.pop() self.size-=1 self._perDown(0) return minvertex def perUp(self,v): i=self.queue.index(v) self._perUp(i) def _perUp(self,i): if i>0: if self.path[self.queue[i]]<=self.path[self.queue[(i-1)/2]]: self.queue[i],self.queue[(i-1)/2]=self.queue[(i-1)/2],self.queue[i] self._perUp((i-1)/2) def _perDown(self,i): left=2*i+1 right=2*i+2 little=i if left<=self.size-1 and self.path[self.queue[left]]<=self.path[self.queue[i]]: little=left if right<=self.size-1 and self.path[self.queue[right]]<=self.path[self.queue[little]]: little=right if little!=i: self.queue[i],self.queue[little]=self.queue[little],self.queue[i] self._perDown(little) if __name__=='__main__': g= Graph() g.addEdge('u','x',1) g.addEdge('u','v',2) g.addEdge('u','w',5) g.addEdge('x','v',2) g.addEdge('x','y',1) g.addEdge('x','w',3) g.addEdge('v','w',3) g.addEdge('y','w',1) g.addEdge('y','z',1) g.addEdge('w','z',5) u=g.getVertex('u') path=Dijkstra(g,u) for v in path: print v.id,path[v]
Solutions: what are common Shortest Path Algorithms in graph theory? What is it?
There are three main types ,,
The first is the most direct greedy dijkstra algorithm, which can be optimized by using the heap data structure. The disadvantage is that it cannot obtain the least short circuit with negative weight and determine the negative ring ,,
The second is the bellman-ford algorithm. Based on the nature of the relaxation operation, we can determine the negative ring, the time complexity is O (nm ,,
The third is the SPFA algorithm. It is not very good to take it out independently as an algorithm. The essence of this algorithm is that the queue optimization time of the bellman-ford algorithm is lower (KE) K value is approximately 2 ,,
Graph Theory-for dijkstra algorithms, urgent
Select the smallest value in the queue. If they are equal, just select one.