【Luogu P1629】 郵遞員送信
阿新 • • 發佈:2020-07-20
題目大意:
一個有向圖,\(n\) 個節點 \(m\) 條邊,求第一個點到各個點的最短路徑與各個點到第一個點的最短路徑之和。
正文:
單源最短路模板題,求 各個點到第一個點的最短路徑
時反著存邊即可。
程式碼:
struct node { int z, to, next; }e[M], dge[M]; int n, m, tot, toto; int dis[N], sid[N], head[N], daeh[N]; bool vis[N]; queue <int> que; void Add(int x, int y, int z) { e[++tot] = (node){z, y, head[x]}, head[x] = tot; } void Dda(int x, int y, int z) { dge[++toto] = (node){z, y, daeh[x]}, daeh[x] = toto; } int SPFA(int s) { memset(dis, 60, sizeof(dis)); memset(vis, 0, sizeof(vis)); for(; !que.empty(); que.pop()); dis[s] = 0, vis[s] = 1; que.push(s); for (; !que.empty(); que.pop()) { int u = que.front();vis[u] = 0; for (int i = head[u]; i; i = e[i].next) { int v = e[i].to; if(dis[v] > dis[u] + e[i].z) { dis[v] = dis[u] + e[i].z; que.push(v); vis[v] = 1; } } } } int AFPS(int s) { memset(sid, 60, sizeof(sid)); memset(vis, 0, sizeof(vis)); for(; !que.empty(); que.pop()); sid[s] = 0, vis[s] = 1; que.push(s); for (; !que.empty(); que.pop()) { int u = que.front();vis[u] = 0; for (int i = daeh[u]; i; i = dge[i].next) { int v = dge[i].to; if(sid[v] > sid[u] + e[i].z) { sid[v] = sid[u] + e[i].z; que.push(v); vis[v] = 1; } } } } int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); Add(u, v, w); Dda(v, u, w); } SPFA(1); AFPS(1); int ans = 0; for (int i = 1; i <= n; i++) ans += dis[i] + sid[i]; printf("%d", ans); return 0; }