HDU 1535:給定有向圖,求從節點 1 到所有其他節點的最短路徑和,加上從所有節點到節點 1 的最短路徑和。
dist1[v] = 1 → v 最短距離dist2[v] = v → 1 最短距離(等價於原圖 v→1)Σ(dist1[i] + dist2[i]),i=2..nconst int INF = 0x3f3f3f3f;
struct Edge { int to, w, next; };
vector<Edge> edges;
vector<int> head;
void add_edge(int u, int v, int w) {
edges.push_back({v, w, head[u]});
head[u] = edges.size() - 1;
}
void spfa(int src, vector<int>& dist) {
int n = head.size() - 1;
dist.assign(n + 1, INF);
vector<bool> inq(n + 1, false);
queue<int> q;
dist[src] = 0;
q.push(src);
inq[src] = true;
while (!q.empty()) {
int u = q.front(); q.pop();
inq[u] = false;
for (int i = head[u]; i != -1; i = edges[i].next) {
int v = edges[i].to;
int w = edges[i].w;
if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
if (!inq[v]) {
q.push(v);
inq[v] = true;
}
}
}
}
}
#include <bits/stdc++.h>
using namespace std;
struct Edge { int to, w, next; };
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T; cin >> T;
while (T--) {
int n, m; cin >> n >> m;
vector<Edge> edges_f, edges_r;
vector<int> head_f(n+1, -1), head_r(n+1, -1);
auto add_f = [&](int u, int v, int w) {
edges_f.push_back({v, w, head_f[u]});
head_f[u] = edges_f.size() - 1;
};
auto add_r = [&](int u, int v, int w) {
edges_r.push_back({v, w, head_r[u]});
head_r[u] = edges_r.size() - 1;
};
for (int i = 0; i < m; ++i) {
int a, b, c; cin >> a >> b >> c;
add_f(a, b, c);
add_r(b, a, c); // 反向邊
}
auto spfa = [&](int src, const vector<int>& head, const vector<Edge>& edges) {
vector<int> dist(n+1, INF);
vector<bool> inq(n+1, false);
queue<int> q;
dist[src] = 0; q.push(src); inq[src] = true;
while (!q.empty()) {
int u = q.front(); q.pop();
inq[u] = false;
for (int i = head[u]; i != -1; i = edges[i].next) {
int v = edges[i].to, w = edges[i].w;
if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
if (!inq[v]) { q.push(v); inq[v] = true; }
}
}
}
return dist;
};
auto dist1 = spfa(1, head_f, edges_f); // 1 -> v
auto dist2 = spfa(1, head_r, edges_r); // v -> 1 (反向圖 1 -> v)
long long ans = 0;
for (int i = 2; i <= n; ++i) ans += dist1[i] + dist2[i];
cout << ans << '\n';
}
return 0;
}
long long邊權非負時,Dijkstra 更穩定:O(m log n),無負環風險。本題邊權為正,可用 Dijkstra。
此題是「多源/匯點最短路轉換」的經典範例,掌握反向圖技巧,能秒殺大量類似問題。