#include <iostream>
#include<cstring>
using namespace std;
const int N = 102, M = 2e4 + 2;
int h[N], e[M], ne[M], w[M], idx;
int path[N], pos[N][N], g[N][N], dist[N][N];
int cnt;
void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void get_path(int i, int j) {
if (pos[i][j] == 0) //说明是直接到达
return;
int k = pos[i][j];
get_path(i, k);
path[cnt++] = k;
get_path(k, j);
}
int main() {
int n, m, i, j, k, u, v, l;
cin >> n >> m;
memset(g, 0x3f, sizeof g);
for (i = 0; i <= n; i++)
g[i][i] = 0;
while (m--) {
cin >> u >> v >> l;
g[u][v] = g[v][u] = min(g[u][v], l);
}
memcpy(dist, g, sizeof g); //是在dist上更新
int res = 1e9;
for (k = 1; k <= n; k++) { //floyd是用邻接矩阵! 因为要随时查找w[i][k]和w[k][j]的值
for (i = 1; i <= k; i++) {
for (j = i + 1; j < k; j++) {
if (res > (long long)dist[i][j] + g[i][k] + g[k][j]) {
res = dist[i][j] + g[i][k] + g[k][j];
cnt = 0;
path[cnt++] = k;
path[cnt++] = i;
get_path(i, j);
path[cnt++] = j;
}
}
}
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++) {
if (dist[i][j] > dist[i][k] + dist[k][j]) {
pos[i][j] = k;
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
if(res==1e9) cout<<"No solution.";
else{
for(i=0;i<cnt;i++) cout<<path[i]<<" ";
}
}
此外 换种方法定义 f[k][i][j]三维是表示经过k条边的最短路径 用快速幂 复杂度为
这样有负环也可以求出最小路径 因为经过的边数是有限制的
因为可以重复经过 i到k经过a条边 k到j经过b条边 是无影响的 就算k到j经过的边在i到k的时候可能经过了 但是题目条件是允许的 所以互相独立也就有结合律 故可以用快速幂
#include <iostream>
#include <map>
#include<cstring>
using namespace std;
const int N = 202; //最多两百个点 离散化
map<int, int> mp;
int m, n, t, s, e;
int res[N][N], g[N][N];
int get(int x) {
if (!mp.count(x))
mp[x] = ++m; //最大编号是m
return mp[x];
}
void l_floyd(int c[][N], int a[][N], int b[][N]) { //是得到2条边+2条边==经过4条边的最短dsit
int i, j, k;
int temp[N][N];
memset(temp, 0x3f, sizeof temp); //一定要初始化INF
for (k = 1; k <= m; k++) {
for (i = 1; i <= m; i++) {
for (j = 1; j <= m; j++) { //可以等于m
temp[i][j] = min(temp[i][j], a[i][k] + b[k][j]);
}
}
}
memcpy(c, temp, sizeof temp);
}
void double_add() {
memset(res, 0x3f, sizeof res);
for (int i = 1; i <= m; i++)
res[i][i] = 0;
while (n) {
if (n & 1)
l_floyd(res, res, g);
l_floyd(g, g, g);
n >>= 1;
}
}
int main() {
int m = 0;
cin >> n >> t >> s >> e; //恰好经过n条边 有t条边 起点s 终点e
s = get(s), e = get(e);
memset(g,0x3f,sizeof g);
int l, u, v, i, j, k;
while (t--) {
scanf("%d%d%d", &l, &u, &v);
u = get(u), v = get(v);
g[u][v] = g[v][u] = min(g[u][v], l);
}
double_add();
cout << res[s][e];
}