Shortest Path

Prove Dijkstra Algorithm

单源最短路径问题的几个算法看过好多遍了,可是每次重看的时候,都不记得为什么要这么做,只是纯粹的记得要这么做而已。今天又翻到,又忘记了原理,终于郁闷了,下决心把自己的推理过程写上来,因为网上真的就还没搜索到完整的证明过程的,也算是做个贡献。当然,我不是Dijkstra,智慧天赋相差甚远,证明过程中难免存在错误纰漏,欢迎有人拍砖指正。

Dijkstra算法实际上求出了一个带权有向图中某一个顶点到其他所有顶点的最短路径,这里只考虑最简单的一种情况,即所有权值(‘weight’ or ‘distance’ or ‘cost’)都是正值(positive number)。

辅助证明的数据结构:

int w[n, n],初始化w[0,0]=0,其余为int.MaxValue(在这里表示无穷大,即不能到达)

bool d[n,n],初始化d[0,0]=true,其余为false,即S到其他点的最短距离尚未求出。

w和d中的第一个分量表示进行到算法的第几次搜索.

符号标记:

设图G(V,E)共有|V|=n个顶点,源点标记为S,序号为0,其余各顶点依次标记为V_1,V_2,…,V_(n-1),用w(S,V_i),i=1,2,…,n-1,来表示源点S到V_i点的权值,也就是距离。

设集合A为:A={V | w[S,V]已经是S至V的最短距离},也就是说,源点到集合A内的任意顶点之间的最短距离是已经求出的,称A内的顶点为已经访问过的顶点(visited vertices)。

设集合B为:B={V | w[S,V]是一中间值},也就是说,此时S至V的最短距离还是未知的,保存的只不过是一个中间值而已,至于中间值如何得出,后面会有说明。称B内的顶点为未访问的顶点(unvisited vertices),可见B是A的补集。

证明:

(I)首先考虑最简单的情况,找找思路。

由于现在只知道S到S的最短距离,也就是0,所以第一步只能考虑从S出发直接到达各点的距离(显然在这个时候考虑路径存在中间顶点没有意义,因为你不能确定S到这个中间顶点的最短路径)。得到S直达各点的w(S,V_i),i=1,2,…,n-1,与w[0,i]比较,w[1,i]保存小值。

这个时候,Dijkstra的做法是选出所有d[0,i],i=0…n-1,为false的对应的w[1,i],i=0…n-1,中的最小值w[1,k]并认为这就是源点S到目标顶点V_k的最短距离。这很好理解,因为假设S到V_k的最短距离是另外一条路径,则必然存在一个中间顶点,不妨设为V_u,u=0…n-1,则有w(S,V_u) + w(V_u, V_k) < w(S,V_k),那么必有w(S,V_u) < w(S,V_k),显然,这与w[1,k]是最小值矛盾,所以w[1,k]就是S到V_k的最短距离,此时把d[1,k]标记为true。

算法的中间值如何得出:

其实以上的叙述已经说明了中间值是如何得到的。设w[x,y]是当前刚确定的源点S到目标定点V_y的最短距离,其中x=0…n-1,y=0…n-1,对所有d[x,i],i=0…n-1,为false的点,更新w[x+1,i]为w[x,i]与(w[x,y]+w(V_y,V_i))的较小值。(I)里的w[x,y]就是w[0,0]。

(II)现在考虑一般情况

设已求得一个集合A,|A|=k,现在求S到第(k+1)个点(注意不一定是V_(k+1),这里的k只是A的基数而已)。

设w[k-1,u],u=0…n-1,是在集合A的基数为k时,所有未访问的w[k-1,i],i=0…n-1,保存的中间值中的最小值(也就是最后一个纳入集合A的顶点,k-1-0+1=k)。标记d[k-1,u]为true,对所有w[k,i],更新d[k-1,i]为false的w[k,i]的值,使其为w[k-1,i]与w[k-1,u]+w(V_u, V_i)的较小值,然后选出d[k,i]为false的所有w[k,i]的最小值w[k,p],p=0…n-1,即源点S到目标顶点p的最短距离,标记d[k,p]为true,继续这一过程,直到某一次求出的最小值为int.MaxValue(表示之后的点都不能到达)。

道理仍然是一样的,如果这个最小值w[k,p]不是源点S到顶点V_p的最短距离,那么设S经过顶点V_t然后到达V_p(V_t是这条路径的倒数第二个顶点)。V_t存在两种可能,要么属于集合A但不是顶点V_u,要么属于集合B。

(i)如果V_t属于A但不是顶点V_u,由于每一个中间值在每求出一个最短距离时都是比较过的,也就是说,在求出S到V_t的最短距离时,S->V_t->V_p的长度必然是和原来的S->V_p的路径长度比较过的,一定会保存下来,则不可能得到当前这个w[k,p],w[k,p]里保存的应该是S经过V_t到V_p的长度而不是S经过V_u到V_p的长度。

(ii)如果V_t属于B,不妨设这条路径为S->V_r->V_o->V_t->V_p,其中V_r属于A,V_o,V_t可以是同一点,也可以是不同点,但是他们都不属于A而是属于B,那么显然有S->V_r->V_o的长度小于S->V_r->V_o->V_t->V_p的长度小于w[k,p],即w[k,o] < w[k,p],与w[k,p]是最小值矛盾。

(iii) 如果路径为S->V_t->V_p且V_t属于B,那么显然S->V_t比S->V_p要近,也就是说,在选择下一个最小值的时候,应该选择w[s,t]而非w[s,p]。

所以,这样一个顶点V_t不存在,一般情况得证。

证毕。

Prove Floyd Algorithm

pending

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值