Advertisement
erek1e

IZhO '18 P2 - Evacuation Plan

Jan 31st, 2023
752
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.19 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <queue>
  5.  
  6. using namespace std;
  7.  
  8. const int INF = 1e9;
  9.  
  10. // DSU
  11. vector<int> parent;
  12. int root(int i) {
  13.     return parent[i] < 0 ? i : (parent[i] = root(parent[i]));
  14. }
  15. void unite(int i, int j) {
  16.     i = root(i), j = root(j);
  17.     if (i == j) return;
  18.     if (parent[i] > parent[j]) swap(i, j);
  19.     parent[i] += parent[j];
  20.     parent[j] = i;
  21. }
  22. inline bool isPath(int i, int j) {
  23.     return root(i) == root(j);
  24. }
  25.  
  26. int main() {
  27.     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  28.     int n, m; cin >> n >> m;
  29.     vector<vector<pair<int, int>>> g(1+n);
  30.     for (int i = 1; i <= m; ++i) {
  31.         int a, b, w;
  32.         cin >> a >> b >> w;
  33.         g[a].emplace_back(b, w);
  34.         g[b].emplace_back(a, w);
  35.     }
  36.     int k; cin >> k;
  37.     vector<bool> npp(1+n);
  38.     for (int i = 1; i <= k; ++i) {
  39.         int x; cin >> x;
  40.         npp[x] = true;
  41.     }
  42.  
  43.     vector<int> distToNPP(1+n, INF);
  44.     priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
  45.     vector<bool> seen(1+n);
  46.     for (int i = 1; i <= n; ++i) {
  47.         if (npp[i]) distToNPP[i] = 0, pq.emplace(0, i);
  48.     }
  49.     while (!pq.empty()) {
  50.         auto [d, v] = pq.top();
  51.         pq.pop();
  52.  
  53.         if (seen[v]) continue;
  54.         seen[v] = true;
  55.  
  56.         for (auto [u, e] : g[v]) {
  57.             int newD = d + e;
  58.             if (newD < distToNPP[u]) {
  59.                 distToNPP[u] = newD;
  60.                 pq.emplace(newD, u);
  61.             }
  62.         }
  63.     }
  64.  
  65.     vector<pair<int, int>> nodesByDist;
  66.     for (int i = 1; i <= n; ++i) nodesByDist.emplace_back(distToNPP[i], i);
  67.     sort(nodesByDist.rbegin(), nodesByDist.rend()); // order by decreasing distance
  68.     vector<int> orderedPosition(1+n);
  69.     for (int i = 0; i < n; ++i) orderedPosition[nodesByDist[i].second] = i;
  70.  
  71.  
  72.     // Parallel Binary Search on queries with DSU
  73.     int q; cin >> q;
  74.     vector<int> a(q), b(q), left(q, 0), right(q, n-1); // nodes up to which index (when ordered by distToNPP)
  75.     for (int i = 0; i < q; ++i) cin >> a[i] >> b[i];
  76.     while (true) {
  77.         vector<pair<int, int>> currentQ; // mid, i
  78.         for (int i = 0; i < q; ++i) {
  79.             if (left[i]+1 < right[i]) currentQ.emplace_back((left[i] + right[i]) / 2, i);
  80.         }
  81.         if (currentQ.empty()) break;
  82.         sort(currentQ.begin(), currentQ.end());
  83.        
  84.         parent = vector<int>(1+n, -1);
  85.         for (int i = 0, nextQ = 0; i < n; ++i) {
  86.             // add edges with both ends on or before ith node in list (nodesByDist)
  87.             int v = nodesByDist[i].second;
  88.             for (auto [u, e] : g[v]) {
  89.                 if (orderedPosition[u] <= i) unite(v, u);
  90.             }
  91.  
  92.             // answer queries
  93.             while (nextQ < (int)currentQ.size() && currentQ[nextQ].first == i) {
  94.                 auto [mid, qIndex] = currentQ[nextQ];
  95.                 bool reachable = isPath(a[qIndex], b[qIndex]);
  96.                 if (reachable) right[qIndex] = mid;
  97.                 else left[qIndex] = mid;
  98.                 ++nextQ;
  99.             }
  100.         }
  101.     }
  102.  
  103.     for (int i = 0; i < q; ++i) cout << nodesByDist[right[i]].first << '\n';
  104.     return 0;
  105. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement