赤裸裸的最小环啊,不过还是觉得用floyd求最小环很神奇, 毕竟它本身就是一种动态规划。
它这道题要求输出路径, 我看到别人写的这种记录pre数组的方法真的太机智了, 我本来是记录i, j, k然后再跑一遍spfa的, 顿时觉得弱爆了。。。
它的pre[i][j] 记录是从i, 到j的最短路中(也就是dis[i][j]中)j前面的那个点。 我也想到了用pre,但是没有想到这种神奇的记录方法, 看来还是要多做题啦。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <time.h>
#include <queue>
#define INF 1 << 29
using namespace std;
int n, m, a[105][105], dis[105][105], step[105], num, pre[105][105];
int main()
{
scanf("%d%d", &n, &m);
if(n == 0)puts("No solution.");
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)a[i][j] = INF, dis[i][j] = INF, pre[i][j] = i;
int x, y, z;
for(int i = 1; i <= m; i ++){
scanf("%d%d%d", &x, &y, &z);
a[x][y] = min(a[x][y], z); a[y][x] = min(a[y][x], z);
dis[x][y] = min(dis[x][y], z); dis[y][x] = min(dis[y][x], z);
}
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 ++)
if(dis[i][j] + a[i][k] + a[k][j] < ans){
ans = dis[i][j] + a[i][k] + a[k][j];
int p = j; num = 0;
while(p != i){
step[++ num] = p;
p = pre[i][p];
}
step[++num] = i;
step[++num] = k;
}
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
if(dis[i][k] + dis[k][j] < dis[i][j])
dis[i][j] = dis[i][k] + dis[k][j], pre[i][j] = pre[k][j];
}
if(ans == INF)puts("No solution.");
else
for(int i = 1; i <= num; i ++)printf("%d ", step[i]);cout<<endl;
return 0;
}