图论网络流相关

一、最短路径问题

1. 所有顶点对的最短路径

动态规划解法一:设 dp[i][j][m] 为顶点 i ~ j 中间最多经过 m 条边时的最短路径,不难得出存在下面状态转移方程 dp[i][j][m] = min{dp[i][k][m-1] + w[k][j]},其中 1<=i<=n。假设原图不存在负权值回路,则对于包含 n 个点的图,任意顶点对 (i, j) 最短路径(简单路径)中间经过的边数最多为 n - 1,因此我们的目标便是求解 dp[i][j][n-1]。上述状态转移过程其实是可以用矩阵快速幂进行优化的,因此我们每次 dp[i][j][m-1]dp[i][j][m] 状态进行松弛操作时,其本质是一种类矩阵乘法的操作,即 dp[i][j][m] = min{dp[i][1][m-1] + w(1, j), dp[i][2][m-1]+w(2, j), ..., dp[i][n][m-1]+w(n,j)}(矩阵乘法 c[i][j] += a[i][k] * b[k][j], 1<=k<=n)。有关矩阵快速幂的应用参考整理的矩阵乘法应用总结。

动态规划解法二(Floyd-Warshall):该算法按照顶点序号 1 ~ n 的顺序,不断将顶点加入到 (i,j)的最短路径中,一步步进行最短路径的松弛计算。设 dp[i][j][k] 表示 i --> j 只经过 (1, 2, .., k) 顶点的最短路径,很容易得到下述状态转移方程 dp[i][j][k] = min(dp[i][j][k-1], dp[i][k][-1] + dp[k][j][k-1]),于是我们要求解的最终状态变成 dp[i][j][n]。另外,由上述状态转移方程可知,对于 dp[i][j][k] 状态的求解只取决于 dp[i][j][k-1],因此利用滚动数组对整个状态转移过程进行空间优化,即状态转移方程变成dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j])。同时,在求解最短路径的过程中,我们可以维护 (i,j)的最短路径上j的前驱节点,设 path[i][j],则 path[i][j] 的状态转移方程如下所示,path[i][j] = path[i][j] or path[k][j]。最后,处理好边界条件,搞起来即可。

const (
	inf  = 0x3f3f3f3f
	maxn = 110
)

var (
	adj  [maxn][maxn]int // 邻接矩阵
	path [maxn][maxn]int // (i,j)最短路径中j的前驱节点
	dp   [maxn][maxn]int // (i,j)最短路径取值
)

// 顶点编号 1 ~ n
func solve(n int) {

	for i := 1; i <= n; i++ {
		for j := 1; j <= n; j++ {
			dp[i][j] = adj[i][j]
			if adj[i][j] >= inf {
				path[i][j] = -1
			} else {
				path[i][j] = i
			}
		}
	}

	for k := 1; k <= n; k++ {
		for i := 1; i <= n; i++ {
			for j := 1; j <= n; j++ {
				if dp[i][j] > dp[i][k]+dp[k][j] {
					dp[i][j] = dp[i][k] + dp[k][j]
					path[i][j] = path[k][j]
				}
			}
		}
	}
}

Floyd-Warshall 算法扩展
该算法为利用动态规划求解图中任意顶点对(i,j)路径上的一些性质,不应该仅仅局限于最短路径这个性质。例如,利用该状态转移过程,同样可以求解:

  • 有向图传递闭包:dp[i][j] |= (dp[i][k]|dp[k][j])

  • (i,j)路径上最长边最小化: dp[i][j] = min(dp[i][j], max(dp[i][k], dp[k][j]))

稀疏图最短路径(Johnson)
简单说下该算法的核心几点:

  • SPFA 判断负权值回路
  • 单源最短路径求解:Dijkstra + Fibonacci Heap
  • 寻找新的权重函数 w' 使得 w'(i,j) 非负且满足新权重函数w'下求解的(i,j)最短路径在旧权重函数w下仍然为最短路径。由于边权值非负,在稀疏图的情况下便可以用Dijkstra+Heap优化最短路径的求解了。
  • 新权重函数构造:w'(i,j) = w(i,j)+h(i)-h(j),其中 h(i)表示添加新源点后源点到i点的最短路径,由于最短路径满足三角不等式 h(j) <= h(i) + w(i,j),所以 w(i,j)非负。w(s,vi) = 0,以 s 为源点求解单源最短路径。

算法导论中关于该算法的流程如下所示:
Johnson算法流程

TODO: 晚上回家学习 Markdown 公式编辑,以后尽量用公式编辑的方式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值