图论的常用技巧
无向图的最小环问题
基于 \(Floyd\) 算法。
先来了解一下 \(Floyd\) 算法的实质:
\(f[k][i][j]\) 表示经过前 \(k\) 个点, \(i\) 到 \(j\) 的最短路径。
\(f[k][i][j] = min(f[k - 1][i][k] + f[k - 1][k][j], f[k][i][j])\)。
发现可以滚动数组优化,最后得到了时间复杂度 \(\mathcal{O}(n^3)\),空间复杂度 \(\mathcal{O}(n^2)\)。
那他是怎么求最小环的呢。
在第一维枚举到 \(k\) 的时候,已经得到了在经过前 \(k - 1\) 点, \(i\) 到 \(j\) 的最短路径。
我们考虑一个环 \(i - j - k - i\)。
\(f[k - 1][i][j]\) 与 \((i, k), (k, j)\) 组成了环。
for(int k = 1; k <= n; k++) {
for(int i = 1; i < k; i++)
for(int j = i + 1; j < k; j++)
ans = min(ans, f[i][j] + dis[i][k] + dis[k][j]);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
}
传递闭包
如果本身有连边或能通过中转点去到达。
如果 \(f[i][j] = 1\) 或者 \(f[i][k] = 1\) 同时 \(f[k][j] = 1\)。
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
f[i][j] |= (f[i][k] & f[k][j]);
差分约束
关于符号的处理:


图论寄巧
浙公网安备 33010602011771号