zoukankan      html  css  js  c++  java
  • 【算法】最短路

    Floyd算法

    计算含负权的图上的多源最短路,原理是动态规划。

    (D_{i,j,k})为从(i)(j)的只以((1...k))集合中的结点为中间结点的最短路的长度。

    1.若最短路经过点(k),则(D_{i,j,k}=D_{i,k,k-1}+D_{k,j,k-1})

    2.若最短路不经过点(k),则(D_{i,j,k}=D_{i,j,k-1})

    因此,(D_{i,j,k}=min(D_{i,j,k-1},D_{i,k,k-1}+D_{k,j,k-1}))

    (以上摘自 Floyd-Warshall算法 - 维基百科

    也就是说,对于任意两个需要求最短路的结点(i,j),我们初始化(D[i][j])为结点(i)直接连接到结点(j)的边的长度(如果不存在这条边,则初始化为(INF)。注意,(INF)取得过大可能导致在加法计算中溢出,建议将(INF)取为"只比最大边权的(m)倍((m)为图的总边数)大一点点"的值)。

    当然为了省事,除了(D[i][i])以外,全部初始化为(INF)也行。

    然后遍历(i,j)之间的中间结点(k),在“经过(k)”与"不经过(k)“两种状态之间取路径更短的。状态的转移由动态规划完成。

    	for (int i = 0; i < n; i++) {
    		for (int j = 0; j < n; j++) {
    			D[i][j] = (i == j ? 0 : INF);
    		}
    	}
    	for (int k = 0; k < n; k++)
    		for (int i = 0; i < n; i++)
    			for (int j = 0; j < n; j++)
    				D[i][j] = min(D[i][j], D[i][k] + D[k][j]);
    

    当我们不关心任意两点间的长度,而只关心两点间是否存在通路时,只需要将预处理部分做些改动,用1和0表示“连通”与“不连通”,将上述代码中D[i][j] = min(D[i][j], D[i][k] + D[k][j])改为D[i][j]=D[i][j]||(D[i][k]&&D[k][j])即可。此时就是在求有向图的传递闭包了。

  • 相关阅读:
    我爱java系列之---【微服务间的认证—Feign拦截器】
    我爱java系列之---【设置权限的三种解决方案】
    581. Shortest Unsorted Continuous Subarray
    129. Sum Root to Leaf Numbers
    513. Find Bottom Left Tree Value
    515. Find Largest Value in Each Tree Row
    155. Min Stack max stack Maxpop O(1) 操作
    painting house
    Minimum Adjustment Cost
    k Sum
  • 原文地址:https://www.cnblogs.com/streamazure/p/12919388.html
Copyright © 2011-2022 走看看