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;
}