题意:求一个点到所有点的最短距离之和加上所有点到这个点距离之和,边为单向边。
解法:先做一次spfa,然后将所有的边反序做一次spfa即可。
代码如下:
#include <iostream> #include <cstring> #include <queue> #include <vector> #include <cstdio> using namespace std; const int MaxN = 1000005; int P, Q, idx, gdis[MaxN], cdis[MaxN]; int head[MaxN], rhead[MaxN]; bool vis[MaxN]; struct Edge { int v, fee, next; }e[MaxN], re[MaxN]; void insert(int a, int b, int c) { ++idx; e[idx].v = b, e[idx].fee = c; e[idx].next = head[a]; head[a] = idx; re[idx].v = a, re[idx].fee = c; re[idx].next = rhead[b]; rhead[b] = idx; } void spfa(Edge e[], int head[], int dis[]) { queue<int>q; memset(vis, 0, sizeof (vis)); dis[1] = 0; vis[1] = true; q.push(1); while (!q.empty()) { int v = q.front(); q.pop(); vis[v] = false; for (int i = head[v]; i != -1; i = e[i].next) { if (dis[e[i].v] > dis[v] + e[i].fee) { dis[e[i].v] = dis[v] + e[i].fee; if (!vis[e[i].v]) { q.push(e[i].v); vis[e[i].v] = true; } } } } } int main() { int T; cin >> T; while (T--) { int a, b, c; memset(head, 0xff, sizeof (head)); memset(rhead, 0xff, sizeof (rhead)); idx = 0; scanf("%d %d", &P, &Q); for (int i = 1; i <= P; ++i) { gdis[i] = cdis[i] = 0x7fffffff; } for (int i = 0; i < Q; ++i) { scanf("%d %d %d", &a, &b, &c); insert(a, b, c); } spfa(e, head, gdis); spfa(re, rhead, cdis); long long tot = 0; for (int i = 2; i <= P; ++i) { tot += gdis[i] + cdis[i]; } cout << tot << endl; } return 0; }