按照集合划分,每次枚举的环最大编号为K,那么这个环是 i到k,k到j,j到i这样一个环,每次算出这个环的长度,递归记录路径即可
总的来说就是把所有的环枚举一遍,比大小
Floyd本质也是所有点的枚举一遍通过中间点更新到其他点的距离
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define ll long long
#define x first
#define y second
typedef pair<int,int> PII;
const int N=110;
int n,m,k,ans,cnt;
PII q[N];
int d[N][N],g[N][N];
int path[N],p[N][N];
void getPath(int i,int j){
if(p[i][j]==0)return;//i与j之间直接相连不存在最短路
int k=p[i][j];
getPath(i,k);//向左递归
path[cnt++]=k;
getPath(k,j); //向右递归
}
int main() {
cin>>n>>m;
memset(g,INF,sizeof g);
while(m--) {
int u,v,w;
cin>>u>>v>>w;
g[u][v]=g[v][u]=min(w,g[u][v]);//假设有u与v之间可以有多条路径
}
ans=INF;
memcpy(d,g,sizeof d);
for(int k=1; k<=n; k++) {
//按照最大值为k分组
for(int i=1; i<k; i++) {
for(int j=i+1; j<k; j++) {
if((ll)g[i][k]+g[k][j]+d[i][j]<ans) {
ans=g[i][k]+g[k][j]+d[i][j];//更新最小换
cnt=0;
path[cnt++]=k;//k--i---j--k
path[cnt++]=i;
getPath(i,j);
path[cnt++]=j;
}
}
}
//floyed
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
if(d[i][j]>d[i][k]+d[k][j]) {
d[i][j]=d[i][k]+d[k][j];
p[i][j]=k;
}
}
}
}
if(ans==INF)puts("No solution.");
else{
for(int i=0;i<cnt;i++)cout<<path[i]<<' ';
cout<<endl;
}
return 0;
}