图论的常用技巧

无向图的最小环问题

基于 \(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]);

差分约束

关于符号的处理:

Tarjan 算法

posted @ 2022-08-11 21:58  TLE_Automation  阅读(32)  评论(0)    收藏  举报