Shortest path
The path with the shortest weighted path length between two vertices is the shortest path.
In a weighted graph, the sum of the weights of the edges experienced from one vertex v to another vertex u is called the sum of weighted paths of the path.
Dijkstra
Single source shortest path of weighted graph
step
- Initialize the array, and initialize the union S to {0};
- Select vj v_j from the vertex set VSvj ,满足 d i s t [ j ] = M i n { d i s t [ i ] , v i ∈ V − S } dist[j] = Min\{dist[i], v_i \in V-S\} dist[j]=Min{ dist[i],vi∈V−S}, v j v_j vjIs the end point of the shortest path currently found, and another S ∪ {j} S\cup \{j\}S∪{ j}
- Modify this time from v 0 v_0v0Go to any vertex vk v_k on the set VSvk The length of the shortest path: if dist[j] + graph[j] [k] <dist[k], then let dist[k] = dist[j] + graph[j] [k]; path[k] = j
- Repeat 2,3 operations n-1 times, until all vertices are included in S
Auxiliary array
- s[]: mark the vertices that have been calculated. The values in the array are all initialized to 0, and the value of the source point index is initialized to 1.
- dist[]: Record the current shortest path length from the source point v0 to other vertices. The value in the array is initialized to the weight from the source point to each vertex edge, namely dist[i]=graph[0] [i]
- path[]: Record the predecessor vertex of the vertex from the shortest path, that is, path[i] is the predecessor vertex of vi on the shortest path from v to vi. Initialization of the values in the array: if there is a directed edge (undirected edge) from the source point v0 to the vertex vi, then path[i] = 0; otherwise, path[i] = -1
Take the following picture as an example:
Initialization: Set dist to be the distance from 0 to all nodes; s[0] is set to 1, and the rest is set to 0; path is set to 0 except for 0 and nodes that cannot be reached from 0.
The first round: find the smallest value in dist [without comparison if the subscript is set to 1 in s], which is the value corresponding to subscript 2, modify the dist and path arrays according to step 3, and set s[2] to 1
Second round: Find the smallest value in dist [without comparison if the subscript is set to 1 in s], which is the value corresponding to subscript 1, modify the dist and path arrays according to step 3, and set s[1] to 1
The third round: Find the smallest value in dist [no comparison if the subscript is set to 1 in s], which is the value corresponding to subscript 3, modify the dist and path arrays according to step 3, and set s[3] to 1
Fourth round: find the smallest value in dist [without comparison if the subscript is set to 1 in s], which is the value corresponding to subscript 4, modify the dist and path arrays according to step 3, and set s[4] to 1
The final result, according to dist, path can get the path and length
Code:
C++
void Dijkstra(Graph G, int v){
int s[G.vexnum];
int path[G.vexnum];
int dist[G.vexnum];
for(int i=0;i<G.vexnum;i++){
dist[i]=G.edge[v][i];
s[i] = 0;
if(G.edge[v][i] < MAX)
path[i]=v;
else
path[i]=-1;
}
s[v]=1;
path[v]=-1;
for(i=0;i<G.vexnum; i++){
int min=MAX;
int u;
for(int j=0; j<G.vexnum; j++){
if(s[j]==0 && dist[j]<min){
min=dist[j];
u=j;
}
}
s[u] = 1;
for(int j=0; j<G.vexnum; j++){
if(s[j]==0 && dist[u] + G.Edges[u][j] < dist[j]){
dist[j] = dist[u] + G.Edges[u][j];
path[j]=u
}
}
}
}
Python
def dijkstra(graph, begin=0):
dist = []
s = []
path = []
nums = len(graph)
# 初始化
for i in range(nums):
dist.append(graph[begin][i])
s.append(0)
if graph[begin][i] < MAX:
path.append(begin)
else:
path.append(-1)
s[begin] = 1
path[begin] = -1
for i in range(nums):
min_dist = MAX
min_vex = -1
for j in range(nums):
if s[j] == 0 and dist[j] < min_dist:
min_dist = dist[j]
min_vex = j
s[min_vex] = 1
for k in range(nums):
if s[k] == 0 and dist[min_vex] + graph[min_vex][k] < dist[k]:
dist[k] = dist[min_vex] + graph[min_vex][k]
path[k] = min_vex
return dist, path
if __name__ == '__main__':
graph = [
[0, 5, 3, MAX, 8],
[MAX, 0, 2, 1, MAX],
[MAX, MAX, 0, MAX, 4],
[MAX, MAX, 1, 0, MAX],
[MAX, MAX, MAX, MAX, MAX]
]
dijkstra(graph)
'''
dist : [0, 5, 3, 6, 7]
path : [-1, 0, 0, 1, 2]
'''
Algorithm complexity O (∣ V ∣ 2) O(|V|^2)O ( ∣ V ∣2)
Dijkstra's algorithm is not suitable for graphs with negative weight edges
Floyd
Shortest path between vertices
Algorithm idea
Recursively generate an n-order square matrix sequence A (− 1), A (0),..., A (k),..., A (n − 1) A^{(-1)}, A^ {(0)}, ...,A^{(k)},...,A^{(n-1)}A(−1),A(0),...,A(k),...,A(n−1)
A ( k ) [ i ] [ j ] A^{(k)}[i][j] A( k ) [i][j]vertexvi v_iviTo vj v_jvj The length of the shortest path, and the number of vertices passed by the path is not greater than k
Recurrence formula
初始化: A ( − 1 ) [ i ] [ j ] = g r a p h [ i ] [ j ] A^{(-1)}[i][j] = graph[i][j] A(−1)[i][j]=graph[i][j]
递推方法: A ( k ) [ i ] [ j ] = M i n { A ( k − 1 ) [ i ] [ j ] , A ( k − 1 ) [ i ] [ k ] + A ( k − 1 ) [ k ] [ j ] } , k = 0 , 1 , . . . , n − 1 A^{(k)}[i][j]=Min\{ A^{(k-1)}[i][j], A^{(k-1)}[i][k]+A^{(k-1)}[k][j]\}, k=0,1,...,n-1 A(k)[i][j]=M i n { A(k−1)[i][j],A(k−1)[i][k]+A(k−1)[k][j]},k=0,1,...,n−1
Code
C++
void Floyd(Graph G){
int A[G.vexnum][G.vexnum];
for(int i=0; i<G.vexnum;i++)
for(int j=0; j<G.vexnum;j++)
A[i][j]=G.Edge[i][j];
for(int k=0;k<G.vexnum;k++)
for(int i=0; i<G.vexnum;i++)
for(int j=0; j<G.vexnum;j++)
if(A[i][j]>A[i][k]+A[k][j])
A[i][j]=A[i][k]+A[k][j];
}
Python
def floyd(graph):
nums = len(graph)
A = []
for i in range(nums):
a = []
for j in range(nums):
a.append(graph[i][j])
A.append(a)
print(A)
for i in range(nums):
for j in range(nums):
for k in range(nums):
if A[i][j] > A[i][k] + A[k][j]:
A[i][j] = A[i][k] + A[k][j]
return A
Take the above picture as an example
if __name__ == '__main__':
graph = [
[0, 5, 3, MAX, 8],
[MAX, 0, 2, 1, MAX],
[MAX, MAX, 0, MAX, 4],
[MAX, MAX, 1, 0, MAX],
[MAX, MAX, MAX, MAX, MAX]
]
# dijkstra(graph)
A = floyd(graph)
print(A)
'''
[[0, 5, 3, 6, 7],
[100, 0, 2, 1, 6],
[100, 100, 0, 100, 4],
[100, 100, 1, 0, 5],
[100, 100, 100, 100, 100]]
'''
Time complexity O (∣ V ∣ 3) O(|V|^3)O ( ∣ V ∣3)