2019中國大學生程序設計競賽(CCPC)—網絡選拔賽-1004-path

  • 2020 年 2 月 18 日
  • 筆記

考慮維護按照邊權最小的堆,維護結點信息如下:

int u; // 上一個結點  int v; // 當前結點  LL lst; // 到上一個結點u的距離  LL now; // 到當前結點v的距離  int id; // 上一個結點u下一次需要擴展的下標

一開始,先將每個結點從最短的那條邊擴展,然後對於每次操作。取隊頭元素,當前的路徑距離就是第$idx$小的路徑,用隊頭元素進行擴展:

  1. 從結點$v$最短的一條邊擴展
  2. 從結點u的$id$下標編號進行擴展

擴展的時候維護上述信息。

這種貪心策略就是很對。

#include <bits/stdc++.h>  using namespace std;    typedef long long LL;  #define dbg(x) cout << #x"=" << x << endl;  #define SZ(x) (int)(x).size()    struct Node{      int u; // 上一個結點      int v; // 當前結點      LL lst; // 到上一個結點u的距離      LL now; // 到當前結點v的距離      int id; // 上一個結點u下一次需要擴展的下標      bool operator<(const Node &b)const{          return now > b.now;      }      void pt(){          dbg(u)          dbg(v)          dbg(lst)          dbg(now)          dbg(id)          dbg("----")      }  };    typedef pair<LL, int> P;  #define w_ first  #define v_ second  const int MAX_M = 5*1e4+100;  int Q[MAX_M], A[MAX_M];  int n,m,q;  vector<P> G[MAX_M];    void solve(){      cin >> n >> m >> q;      for(int i = 1; i <= n; ++i) G[i].clear();      int u,v;      LL w;      priority_queue<Node> que;      for(int i = 1; i <= m; ++i){          cin >> u >> v >> w;          G[u].push_back(make_pair(w, v));      }      int mxK = 0;      for(int i = 1; i <= q; ++i){          cin >> Q[i];          mxK = max(mxK, Q[i]);      }      for(int i = 1; i <= n; ++i){          sort(G[i].begin(), G[i].end());          if(SZ(G[i])){ // 從G[i]最小的擴展出一條邊              P e = G[i][0];              que.push((Node){i, e.v_, 0, e.w_, 1});          }      }      int idx = 0;      /*      int u; // 上一個結點      int v; // 當前結點      LL lst; // 到上一個結點u的距離      LL now; // 噹噹前結點v的距離      int id; // 上一個結點u需要擴展的下標      */      while(idx < mxK){          Node p = que.top();          que.pop();          A[++idx] = p.now;          // 從v擴展當前結點最小的邊          if(SZ(G[p.v])) {              P e = G[p.v][0];              que.push((Node){p.v, e.v_, p.now, p.now+e.w_, 1});          }          // 通過G[p.u][p.id]擴展          if(p.id < SZ(G[p.u])){              P e = G[p.u][p.id];              que.push((Node){p.u, e.v_, p.lst, p.lst+e.w_, p.id+1});          }      }      for(int i = 1; i <= q; ++i){          cout << A[Q[i]] << endl;      }  }    int main(){  	//freopen("in.txt", "r", stdin);  	ios::sync_with_stdio(0); cin.tie(0);      int T;      cin >> T;      while(T--) solve();      return 0;  }