OSDN Git Service

修复了最小环问题.
authorTrisolaris HD <36555123+TrisolarisHD@users.noreply.github.com>
Fri, 29 Mar 2019 12:47:48 +0000 (20:47 +0800)
committerGitHub <noreply@github.com>
Fri, 29 Mar 2019 12:47:48 +0000 (20:47 +0800)
docs/graph/min-circle.md

index 83f980b..73b19df 100644 (file)
 
 ### Floyd
 
-最小环是自己到自己的距离,所以我们强迫最短路出去跑一遍就行了
+记原图中 $u,v$ 之间边的边权为 $val\left(u,v\right)$
 
\80\8eä¹\88强迫ï¼\9f
\88\91们注æ\84\8få\88° Floyd ç®\97æ³\95æ\9c\89ä¸\80个æ\80§è´¨ï¼\9aå\9c¨æ\9c\80å¤\96å±\82循ç\8e¯å\88°ç\82¹ $k$ æ\97¶ï¼\88å°\9aæ\9cªå¼\80å§\8b第 $k$ æ¬¡å¾ªç\8e¯ï¼\89ï¼\8cæ\9c\80ç\9f­è·¯æ\95°ç»\84 $dis$ ä¸­ï¼\8c$dis_{u,v}$ è¡¨ç¤ºç\9a\84æ\98¯ä»\8e $u$ å\88° $v$ ä¸\94ä»\85ç»\8fè¿\87ç¼\96å\8f·å\9c¨ $\left[1, k\right)$ å\8cºé\97´ä¸­ç\9a\84ç\82¹ç\9a\84æ\9c\80ç\9f­è·¯ã\80\82
 
-对于所有的 $i$ ,使它自己到自己的距离为 $\infty$ ,也就是
+由最小环的定义可知其至少有三个顶点,设其中编号最大的顶点为 $w$,环上与 $w$ 相邻两侧的两个点为 $u,v$,则在最外层循环枚举到 $k=w$ 时,该环的长度即为 $dis_{u,v}+val\left(v,w\right)+val\left(w,u\right)$。
 
-```cpp
-dis[i][i] = (1 << 30);
-```
-
-然后利用 Floyd 的性质,跑完之后对所有的 $dis[i][i]$ 取 $\min$ 即可。
+故在循环时对于每个 $k$ 枚举满足 $i<k,j<k$ 的 $(i,j)$,更新答案即可。
 
 时间复杂度: $O(n^3)$ 
 
+下面给出 C++ 的参考实现:
+
+```cpp
+int val[maxn + 1][maxn + 1]; // 原图的邻接矩阵
+inline int floyd(const int &n) {
+       static int dis[maxn + 1][maxn + 1]; // 最短路矩阵
+       for (int i = 1; i <= n; ++i)
+               for (int j = 1; j <= n; ++j)
+                       dis[i][j] = val[i][j]; // 初始化最短路矩阵
+       int ans = inf;
+       for (int k = 1; k <= n; ++k) {
+               for (int i = 1; i < k; ++i)
+                       for (int j = 1; j < i; ++j)
+                               ans = std::min(ans, dis[i][j] + val[i][k] + val[k][j]); // 更新答案
+               for (int i = 1; i <= n; ++i)
+                       for (int j = 1; j <= n; ++j)
+                               dis[i][j] = std::min(dis[i][j], dis[i][k] + dis[k][j]); // 正常的 floyd 更新最短路矩阵
+       } return ans;
+}
+```
+
 ## 例题
 
 GDOI2018 Day2 巡逻