​http://acm.hdu.edu.cn/showproblem.php?pid=1599​

floyd求最小环问题 有向图的话 跑一遍模板然后n^2扫一遍就好 但是无向图不能这样无脑搞 比如三阶完全图 边权都相等 那就不存在松弛了 明明有环但是判不出 想通过记录最小次小值来搞又会出现重点问题 比如题目第二个样例 dis[1][3]=2 dis[3][2]=1=>dis[1][2]=3 这样本来没环给判出环了

最外层循环到k的话 说明[1,k-1]都已经发挥了松弛作用 也就是说当前任意两点之间被松弛的最短距离 都是由[1,k-1]确定的 与[k,n]无关 这样可以枚举[k,n]来通过e[i][k]+e[k][j]+dis[i][j](i,j<k)来找出最小环 但是[k+1,n]目前可以确定的环之后可定会被算上 只用k这个点扫一遍就完事了

 

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1000000000;
const int maxn=1e2+10;

ll e[maxn][maxn],dis[maxn][maxn];
int n,m;

ll floyd()
{
ll res;
int i,j,k;
res=N;
for(k=1;k<=n;k++){
for(i=1;i<=k-1;i++){
for(j=i+1;j<=k-1;j++){
res=min(res,dis[i][j]+e[i][k]+e[k][j]);
}
}
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
return res;
}

int main()
{
ll ans,w;
int i,j,u,v;
while(scanf("%d%d",&n,&m)!=EOF){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
if(i==j) e[i][j]=0;
else e[i][j]=N;
}
}
while(m--){
scanf("%d%d%lld",&u,&v,&w);
e[u][v]=min(e[u][v],w);
e[v][u]=min(e[v][u],w);
}
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
dis[i][j]=e[i][j];
}
}
ans=floyd();
if(ans==N) printf("It's impossible.\n");
else printf("%lld\n",ans);
}
return 0;
}