图论模型:最小路径算法

基础理论

图,有向图,无向图的定义这里从略。

定义1 无环,无重边的图称为简单图。

定义2 任意两顶点均相邻的简单图称为完全图。含有n个顶点的完全图记为

定义3 顶点的度:

(1)在无向图中,与顶点v关联的边的数目(环算两次)称为这个点的度,记为

(2)在有向图中,从顶点v引出的弧的数目称为v的v的出度,记为,从该点引入的弧的数目称为入度,记为,两者相加之和记为顶点的度。

定理1 对任意图,有

推论:任何图中的奇顶点总数为偶数.

图的矩阵表示

1.关联矩阵
对于无向图 ,其关联矩阵 ,其中

对于无向图其关联矩阵 ,其中

2.邻接矩阵

对于无向赋权图 ,其邻接矩阵 ,其中

对于有向赋权图,上式改为:

最短路算法

1.Dijkstra算法(贪心算法)
这是一种贪心算法,其主要用到的是迭代方法。它的依据是一个重要且明显的性质:最短路是一条路,它的任意子路也是该子路两端点间的最短路
该算法的核心思想是:从起点由近及远地求得到各点的最短路和距离,直到到达某个顶点
为了避免重复并保留每一步的计算信息,对于任意顶点定义两个记号:

算法的操作可以这样表示:

令起点

其中,表示顶点u和v之间边的权值.如果利用上一个节点对当前节点的进行了修改,则
,否则不变.
计算,把达到这个最小值的一个顶点即为,令
算法用伪代码表示如下:
Q = G.V // Q 是一个优先队列,按 排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 主循环
DIJKSTRA(G, w, s)
// 初始化
for each vertex v in G.V:
l(v) = ∞
z(v) = NIL
l(s) = 0
S_i =
while Q is not empty:
u = EXTRACT-MIN(Q) // 从 Q 中取出 l(v) 最小的顶点 u
S_i = S_i ∪ {u} // 将 u 加入永久标号集合 S_i
for each vertex v in G.Adj[u]: // 遍历 u 的所有邻接顶点 v
if l(v) > l(u) + w(u, v): // 松弛操作
l(v) = l(u) + w(u, v)
z(v) = u
DECREASE-KEY(Q, v, l(v)) // 更新 Q 中 v 的优先级

下面是用python实现的算法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import heapq

def dijkstra(graph, start):
# 初始化距离字典和父顶点字典
l = {vertex: float('inf') for vertex in graph}
z = {vertex: None for vertex in graph}
l[start] = 0 # 起点的距离为0

# 使用优先队列存储 (距离, 顶点) 对
priority_queue = [(0, start)]

while priority_queue:
current_distance, u = heapq.heappop(priority_queue)

# 如果当前距离大于已知最短距离,则跳过
if current_distance > l[u]:
continue

# 遍历邻接顶点
for v, weight in graph[u].items():
distance = current_distance + weight

# 如果发现更短路径,则更新
if distance < l[v]:
l[v] = distance
z[v] = u
heapq.heappush(priority_queue, (distance, v))

return l, z

# 示例图的邻接表表示
graph = {
'A': {'B': 1, 'C': 4},
'B': {'A': 1, 'C': 2, 'D': 5},
'C': {'A': 4, 'B': 2, 'D': 1},
'D': {'B': 5, 'C': 1}
}

l, z = dijkstra(graph, 'A')
print("最短距离:", l)
print("父顶点记录:", z)

2.Floid算法:(动态规划)

如果一个节点位于起点到重点的最短距离路径上,以节点0→8为例,

  1. Python代码(片段):
1
2
3
4
5
6
for k in range(self.V):
for i in range(self.V):
for j in range(self.V):
if self.D[i][k]+self[k][j]<self.D[i][j]:
self.D[i][j]=self.D[i][k]+self[k][j]
self.S[i][j]=self.S[i][k]