已知图中从一点到另一点的距离,从1号点到另一点再从这一点返回1号点,求去到所有点的距离之和最小值
*解法:正着反着分别建图,把到每个点的距离加起来
spfa跑完之后dist数组就是从起点到每一点的最短距离
get反着建图这种技能
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; #define SZ 1000005 #define INF 1e18+10 long long dist[SZ], tmp[SZ], dis = 0; int head[SZ], nxt[SZ], tot = 0; int x[SZ], y[SZ]; long long z[SZ]; int use[SZ]; struct edge { int t; long long d; }l[SZ]; void build(int f, int t, long long d) { l[++tot] = (edge){t, d}; nxt[tot] = head[f]; head[f] = tot; } queue<int> q; int p, qq; void spfa() { for(int i = 1; i <= p; i++) dist[i] = INF, use[i] = 0; use[1] = 1, dist[1] = 0; q.push(1); while(q.size()) { int u = q.front(); q.pop(); use[u] = 0; for(int i = head[u]; i; i = nxt[i]) { int v = l[i].t; if(dist[v] > dist[u] + l[i].d) { dist[v] = dist[u] + l[i].d; if(!use[v]) use[v] = 1, q.push(v); } } } } int main() { int T, s = 1; scanf("%d", &T); while(T--) { scanf("%d %d", &p, &qq); dis = 0; tot = 0; for(int i = 0; i < qq; i++) head[i] = nxt[i] = use[i] = 0; for(int i = 0; i < qq; i++) { scanf("%d %d %lld", &x[i], &y[i], &z[i]); build(x[i], y[i], z[i]); } spfa(); for(int i = 1; i <= p; i++) tmp[i] = dist[i]; tot = 0; for(int i = 0; i < qq; i++) head[i] = nxt[i] = use[i] = 0; for(int i = 0; i < qq; i++) build(y[i], x[i], z[i]); spfa(); for(int i = 1; i <= p; i++) dis = dis + tmp[i] + dist[i]; printf("%lld ", dis); } return 0; }