学习了一下最短路的姿势,这个建图方法好妙啊,虽然不会证明正确性……
#include <bits/stdc++.h> #define N 220000 #define INF 1000000000 using namespace std; int n, m; int ai[N], bi[N], ci[N], di[N]; int check; class DIJ { private: struct node {int t, d;}; struct comp {int operator () (node a, node b) {return a.d > b.d;}}; priority_queue <node, vector <node>, comp> Q; public: vector <int> bi[N], ci[N]; int dis[N], vis[N], pre[N]; int tot; void build(int a, int b, int c) { bi[a].push_back(b); ci[a].push_back(c); //if (check) printf("%d %d %d ",a,b,c); } void solve() { for (int i = 2; i <= tot; ++ i) dis[i] = INF, vis[i] = 0; dis[1] = vis[1] = 0; Q.push((node){1, 0}); while (!Q.empty()) { int hd; do hd = Q.top().t, Q.pop(); while (vis[hd] && !Q.empty()); if (vis[hd]) break; else vis[hd] = 1; for (int j = 0; j < bi[hd].size(); ++ j) if (dis[hd] + ci[hd][j] < dis[bi[hd][j]]) { dis[bi[hd][j]] = dis[hd] + ci[hd][j]; pre[bi[hd][j]] = hd == 1? bi[hd][j]: pre[hd]; Q.push((node){bi[hd][j], dis[bi[hd][j]]}); } } } } A, B; int tot, ans = INF, bac = INF, pp; int main() { scanf("%d%d", &n, &m); A.tot = n; B.tot = n + 1; for (int i = 1; i <= m; ++ i) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); tot ++; ai[tot] = a; bi[tot] = b; ci[tot] = c; tot ++; ai[tot] = b; bi[tot] = a; ci[tot] = d; A.build(a, b, c); A.build(b, a, d); if (a == 1 || b == 1) if (bac > c + d) bac = c + d, pp = (a == 1? b: a); } A.solve(); A.dis[1] = bac; A.pre[1] = pp; check = 1; for (int i = 1; i <= tot; ++ i) { if (ai[i] == 1) { if (A.pre[bi[i]] != bi[i]) B.build(1, bi[i], ci[i]); } else if (bi[i] == 1) { if (A.pre[ai[i]] != ai[i]) B.build(1, n + 1, A.dis[ai[i]] + ci[i]); else B.build(ai[i], n + 1, ci[i]); } else if (A.pre[ai[i]] != A.pre[bi[i]]) B.build(1, bi[i], A.dis[ai[i]] + ci[i]); else B.build(ai[i], bi[i], ci[i]); } B.solve(); printf("%d ", B.dis[n + 1]); }