题意很清楚 就是输出一个最小环的路径
我们要找到一条从 i 到 i 的最小环
就可以拆成找 i-k 和 k-j 和 j-i 的最短路径
这样就用到了中间点 k 去更新路径
可以发现这就是Floyd算法找中间点去更新最短路径的思想
先规定一个最大点 k 去枚举 k 这样保证 i-j 的路径中不会出现k这个点
这样就保证了在 i-j 的路径中不存在环
既然要保存路径,就得要一个数组去存储当前点的上一个点
以便于寻找路径时可以迅速找到连接点
每次更新记得更改当前点的前一个点即可
int n,m,ans,cnt;
int mp[110][110]; // 记录两个点之间的边
int dis[110][110];
int pre[110][110]; // 记录当前点的前一个点
int path[110]; // 记录路径
void Floyd(){
for(int k=1;k<=n;k++){
for(int i=1;i<k;i++){
for(int j=i+1;j<k;j++){
if(ans > mp[i][k] + mp[k][j] + dis[i][j]){ // 成环条件
ans = mp[i][k] + mp[k][j] + dis[i][j];
cnt = 0;
int t = j;
while(t != i){ // 从j开始往前存点
path[++cnt] = t;
t = pre[i][t];
}
path[++cnt] = i;
path[++cnt] = k;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(dis[i][j] > dis[i][k] + dis[k][j]){
dis[i][j] = dis[i][k] + dis[k][j];
pre[i][j] = pre[k][j];
}
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
ans = INF;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
pre[i][j] = i;
mp[i][j] = mp[j][i] = dis[i][j] = dis[j][i] = INF;
}
}
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
dis[u][v] = dis[v][u] = mp[u][v] = mp[v][u] = min(mp[u][v],w);
}
Floyd();
if(ans == INF) cout << "No solution." << endl;
else{
for(int i=1;i<cnt;i++) cout << path[i] << " ";
cout << path[cnt] << endl;
}
return 0;
}