图论 最小环 Floyd

概念

最小环:指一个由n个点构成的图中,边权和最小的环。(n >= 3)。

最小环分为有向图最小环无向图最小环

方法

n为点的个数,m为边的条数。

三种解法:
一、暴力
时间复杂度O(n2 m)
每次枚举删一条边line,这条边的两个端点为u,v,求取在删除这条边后,u,v的最短距离dis,则含有这条被删除的边的最小的环的长度为 dis + line

二、Dijkstra
时间复杂度O( m ( n + m ) l o g n m(n + m)log n m(n+m)logn
还是枚举删边,只是用dijkstra优化了求u,v最短距离的过程

三、Floyd
时间复杂度O(n3

设原图的点 u u u与点 v v v之间的边的边权为 v a l ( u , v ) val(u,v) valuv

首先,我们先来看到Floyd算法,我们知道Floyd这个算法,在最外层循环枚举到K时(尚未开始第K次循环),最短路dis数组中, d i s [ u ] [ v ] dis[u][v] dis[u][v]表示的是从u点到v点且仅经过编号在[1,K)区间中的点的最短路

由最小环的定义可以知道至少有三个顶点,设其中编号最大的顶点为w,环上与w相邻两侧的两个点为u,v,那么在最外层循环枚举到k = w时该环的长度即为 d i s [ u ] [ v ] + v a l ( v , w ) + v a l ( w , u ) dis[u][v] + val(v, w) + val(w, u) dis[u][v]+val(v,w)+val(w,u)

所以在循环时对于每一个 k k k ,枚举满足 i &lt; k , j &lt; k i &lt; k, j &lt; k i<k,j<k ( i , j ) (i , j) (i,j), 更新答案即可。

Floyd解法代码

const int maxn = 1e3 + 10;
const int INF = 0x3f3f3f3f;
int val[maxn][maxn];	//边权
int dis[maxn][maxn];	//最短距离
int floyd(int n)
{
	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 = 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] = min(dis[i][j], dis[i][k] + dis[k][j]);
	}
	return ans;
}

参考来源

OI wiki
https://oi-wiki.org/graph/min-circle/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值