题解
- 求最小环的方法是,删掉任意两点i和j之间的边,求i和j的最短路,再加上i和j之间的边。
- 可用floyd算法求解。floyd算法的特点是当以k为中间结点时,以i和j为两端的点必定是经过1——k-1点的最短路。
- 我们假设最小环经过
三点且满足
,那么当floyd遍历到k时,已经知道了经过以i和j为两端的点经过1——k-1的最短路。那么最小环为
。
#include <bits/stdc++.h>
using namespace std;
int const inf = 100000000;
int const N = 100 + 10;
int dis[N][N],val[N][N],n,m;
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) dis[i][j] = val[i][j] = 0;
else dis[i][j] = val[i][j] = inf;
}
}
for(int i=1;i<=m;i++){
int u,v,len;
scanf("%d%d%d",&u,&v,&len);
dis[u][v] = dis[v][u] = min(dis[v][u],len); //dis记录两点之间的最短路径
val[u][v] = val[v][u] = min(val[v][u],len); //val记录相邻两点之间的长度
}
int mindist = inf;
for(int k=1;k<=n;k++){ //环上三个点i,j,k满足j<i<k,
for(int i=1;i<k;i++){ //根据floyd算法,必定经过以i和j为端点,经过1——k-1
for(int j=1;j<i;j++){
mindist = min(mindist,dis[i][j] + val[i][k] + val[k][j]);
}
}
for(int i=1;i<=n;i++){ //常规的floyd算法,以i和j为端点,经过1——k
for(int j=1;j<=n;j++){
if(dis[i][k] != inf && dis[k][j] != inf){
dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);
}
}
}
}
if(mindist >= inf) printf("It's impossible.\n");
else printf("%d\n",mindist);
}
return 0;
}