Files
Data-Structure/模板//Floyd最短路径.cpp
2025-12-16 20:36:27 +08:00

106 lines
3.7 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author: e2hang 2099307493@qq.com
* @Date: 2025-12-12 13:49:24
* @LastEditors: e2hang 2099307493@qq.com
* @LastEditTime: 2025-12-12 13:50:06
* @FilePath: \undefinedd:\code\Git-DataStructureAlgorithms\模板\图\Floyd最短路径.cpp
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = (ll)4e18; // 足够大的无穷(要确保 INF + INF 不溢出)
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
// 输入: n = 顶点数, m = 边数
// 顶点编号假定为 1..n
if (!(cin >> n >> m)) return 0;
// 距离矩阵 d和 next 矩阵用于路径恢复
vector<vector<ll>> d(n+1, vector<ll>(n+1, INF));
vector<vector<int>> nxt(n+1, vector<int>(n+1, -1));
// 初始化:距离为 INF自身为0
for (int i = 1; i <= n; ++i) {
d[i][i] = 0;
nxt[i][i] = i; // 可选:表示到自身的下一跳是自己
}
// 读边(有向图)。若是无向图,请同时赋值两个方向
// 若图中可能有多条边,取较小的权重
for (int i = 0; i < m; ++i) {
int u, v;
long long w;
cin >> u >> v >> w;
if (w < d[u][v]) {
d[u][v] = w;
nxt[u][v] = v; // 初始从 u 到 v 的下一跳是 v
}
}
// FloydWarshall 主循环
for (int k = 1; k <= n; ++k) {
for (int i = 1; i <= n; ++i) {
if (d[i][k] == INF) continue; // 剪枝i->k 不可达就跳过
for (int j = 1; j <= n; ++j) {
if (d[k][j] == INF) continue; // 剪枝k->j 不可达就跳过
ll through = d[i][k] + d[k][j];
if (through < d[i][j]) {
d[i][j] = through;
nxt[i][j] = nxt[i][k]; // 路径恢复:先走 i->k 的第一步
}
}
}
}
// 检测负权回路:若任何 d[i][i] < 0 表示存在负环(经过该顶点的路径可以无限变小)
bool has_negative_cycle = false;
for (int i = 1; i <= n; ++i) {
if (d[i][i] < 0) {
has_negative_cycle = true;
break;
}
}
// 输出示例(可按需修改)
if (has_negative_cycle) {
cout << "Graph contains a negative-weight cycle reachable from some vertices.\n";
// 竞赛中通常要求你输出并退出或按题意处理
} else {
// 示例:输出任意两点间的最短距离矩阵(不可达输出 INF 表示)
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
if (d[i][j] >= INF/4) cout << "INF";
else cout << d[i][j];
if (j < n) cout << ' ';
}
cout << '\n';
}
}
// 示例:如何恢复一条具体的最短路径(从 u 到 v
auto get_path = [&](int u, int v) -> vector<int> {
vector<int> path;
if (nxt[u][v] == -1) return path; // 不可达
int cur = u;
path.push_back(cur);
while (cur != v) {
cur = nxt[cur][v];
// 防止无限循环(理论上 nxt 应该使得路径在 n 步内结束)
if (cur == -1) return vector<int>();
path.push_back(cur);
if ((int)path.size() > n+5) return vector<int>(); // 保护措施:出现异常则返回空
}
return path;
};
// (可选)读取查询并输出路径示例:
// int q; cin >> q; while(q--){ int u,v; cin>>u>>v; auto p=get_path(u,v); ... }
return 0;
}