图上最小的环
概述
最小环问题,又称The Shortest Circle.
是指在一个图中,有n个节点构成的边权和最小的环($n \geq 3$),一般来说,最小环分为有向图最小环和无向图最小环。
也就是在一张图上从一个点出发,经过一条简单路径回到起点成为环.图的最小环就是所有环中长度最小的。
解决方法
最小环问题有好几种解决方法。
朴素算法求最小环
朴素算法就非常简单了。
首先令$min(i,j)$表示删除$e(i,j)$这条边之后$i$到$j$的最短路。
那么最小环的长度就是$min(u,v) + e(u,v)$。
时间复杂度:$O(EV^2)$。
带权并查集求最小环
例题:LuoguP2661
Solution
本题中要求求的是有向图最小环。
我们把每一位同学看成一个节点,分别向他们信息传递的对象连有向边,那么问题就转化成了最小环。
这里我们用带权并查集来解决问题。
假如说第$i$号同学的信息传递对象是第$j$号同学,那么连一条有向边$e(i,j)$。
同时,我们更新$i$号点到其父节点的路径,$i$节点到其父节点的路径长即为$j$号点到其父节点的路径长+1。
那么这样建完图之后,游戏的轮数就是这张图中最小环的长度。
如果两个点祖先节点相同,那么显然它们可以构成一个环,这时我们更新最小环长度。
对当前最小环长度和这两个点到其祖先节点长度之和+1取个$min$即可。
代码
1 | /* Headers */ |
Floyd求最小环
顾名思义,在Floyd的同时,顺便算出最小环。
Floyd算法在求解最短路时,最外层的循环保证了当循环到$k$时,所有节点都已经求得$0 … k-1$为中间点的最短路。
我们知道,一个环至少由$3$个节点构成。
假设某一个环中编号最大的节点为$k$,在环中与之左右相连的点的编号为$i,j$。
那么最大编号为$k$的最小环长度为$Minc = dist_{i,j} + Graph_{i,k} + Graph_{k,j}$。
其中$dist_{i,j}$表示以$0…k-1$号点为中间点时的最短路径。
这时,我们会发现:这刚好符合Floyd算法最外层循环到$k$时的情况,则此时对$i,j$循环所有编号小于$k$的顶点组合即可找到最大编号为$k$的最小环。
然后再经过最外层循环,即可找到整个图的最小环。
代码
1 | int Minc = inf; |
例题: HDU1599
非常简单的最小环模板题。
注意初始化的时候要把$dist$和$Graph$数组设置为无穷大(即避免自环)。
最后注意一下输入格式即可。
代码
1 | /* Headers */ |