HDU 1599 find the mincost route(最小环)

题意:给定带权无向图,可能有重边,求至少结点数为3的最小环,这里环的权值定义为环上带权边的权值之和。


思路 f l o y d floyd floyd解决,考虑遍历到第 k k k个中转站时,我们已经求出 i , j < k i,j<k i,j<k时的最短路 d [ i ] [ j ] d[i][j] d[i][j],所以若 i , j , k i,j,k i,j,k在一个环上的话,则 a n s = m i n ( a n s , d [ i ] [ j ] + g [ i ] [ k ] + g [ k ] [ j ] ) ans=min(ans,d[i][j]+g[i][k]+g[k][j]) ans=min(ans,d[i][j]+g[i][k]+g[k][j]) g [ i ] [ k ] , g [ k ] [ j ] g[i][k],g[k][j] g[i][k],g[k][j]代表边权,这样我们就可以利用 f l o y d floyd floyd不断更新 a n s ans ans,从而满足找到最小环。


注意:因为更新 a n s ans ans时因为右边是三个状态相加,所以 i n f inf inf要开 1 e 8 1e8 1e8,避免爆 i n t int int

还有就是建图时,需要注意重边的时候取最小的边权。


时间复杂度: O ( n 3 ) O(n^3) O(n3)

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=120,M=2e4+5,inf=1e8+7,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
int n,m,g[N][N],d[N][N]; 
int floyd(){
	int ans=inf;
	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,d[i][j]+g[i][k]+g[k][j]);
		for(int i=1;i<=n;i++)
			if(d[i][k]!=inf)
				for(int j=1;j<=n;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); 
	}
	return ans;
}
int main(){
	while(~scanf("%d%d",&n,&m)){ 
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++) if(i!=j) d[i][j]=g[i][j]=inf;
	for(int i=1,u,v,w;i<=m;i++)
		scanf("%d%d%d",&u,&v,&w),g[u][v]=g[v][u]=d[u][v]=d[v][u]=min(g[u][v],w);	
	int ans=floyd();
	if(ans==inf) puts("It's impossible.");
	else printf("%d\n",ans);
	}
	return 0;
}