dijkstra算法的证明
一直没法证明为什么该算法求出的就能是最短路径,看了很多别的博客想了很久,提出来一个证明方法,望指正
一.归纳前的符号准备
符号 | 含义 | 初值 |
---|---|---|
visited[u] | u 是否已经纳入已确定最短路径的集合 | false |
distance_now[u] | u 现在到达起点的最短距离(计算过程中会一直更新) | + ∞ +\infty +∞ |
distance_short[u] | u 到起点的最短距离(实际上的答案) | ans |
visited集合 | 已经纳入已确定最短路径的点的集合 | \ |
un_visited集合 | 尚未纳入已确定最短路径的点的集合 | \ |
dis[i] [j] | 从i到j的边权 |
二.关于dijkstra算法的过程描述
-
将起点u放入visited集合
-
利用u更新其他所有节点的distance_now,更新方式为distance_now[v] = min{distance_now[v],distance_now[u]+distance[u] [v]}
即取:通过s~中转到u的距离与原距离的最小值
-
从un_visited集合中,找出最小的distance_now[u],将u点从un_visited移除,加入visited中
-
重复2和3直至终点已被纳入visited集合,即可得出起点到终点的最短距离
三.证明
1.命题描述
算法纳入n个点时,visited集合(此时有n个节点)中的每个节点i的distance_now[i]等于最短路径distance_short[i]
2.归纳基础
当n=1时,纳入的是起点s,且distance[s]=0,是最短路径
3.归纳假设
假设当n=k时,假设成立,即算法纳入k个点时,visited集合(此时有k个节点)中的每个节点i的distance_now[i]等于最短路径distance_short[i]
那么,当n=k+1时,visited集合(此时有k+1个节点)中的每个节点i的distance_now[i]等于最短路径distance_short[i]也成立
引入定理
- 最短路径的子路径也是最短路径
- 如果从s到k+1的最短路径L的节点不全在visited集合中,记L经过的visited集合中的最后一个节点为last,则last与v必然不直接相连
证明:若直接相连,则该L = distance_short[last]+dis[last] [k+1] 然而在集合visited加入last节点之后,对以last为中转节点的所有distance_now进行了更新,distance_now[k+1]必然<= distance_short[last]+dis[last] [k+1] ,distance_now[k+1]比L更小,这与L是最短路径矛盾,所以节点last必然不可能与k+1直接相连
反证法
-
如果假设不成立,那么这个不成立假设只会是
加入的第k+1点的距离distance_now[k+1]不是最短路径 -
那么存在一条从s到k+1的最短路径L,这条路径的点并不全在visited集合中(如果全部存在visited中,因为是在纳入k个点后进行了距离更新,这个dis就是由visited集合中的点进行更新的,就是最短路径)
-
记L上最后一个在visited集合中的节点为last,那么L=distance_short[last]+从last到k+1的最短距离> distance_short[last] (非负权值图中last到k+1的最短距离肯定大于0)
-
由定理2可得:如果从s到k+1的最短路径L的节点不全在visited集合中,记L经过的visited集合中的最后一个节点为last,则last与v必然不直接相连,不妨设last与k+1中隔了m个节点(以下仅针对m=1时候做出证明,容易得出当m>1时也成立)
-
设隔的这个节点为y,那么在这里y与last直接相连
-
由定理1:最短路径的子路径也是最短路径,那么distance_short[last]+dis[last] [y]也是最短路径
-
但是由定理2可得:如果从s到y的最短路径L的节点不全在visited集合中,记L经过的visited集合中的最后一个节点为last,则last与y必然不直接相连
这与y与last直接相连矛盾 -
所以加入的第k+1点的距离distance_now[k+1]不是最短路径这一假设不成立,所以加入的第k+1点的距离distance_now[k+1]是最短路径