Submission #395272

#TimeUsernameProblemLanguageResultExecution timeMemory
395272rama_pangEvacuation plan (IZhO18_plan)C++17
100 / 100
833 ms69716 KiB
#include <bits/stdc++.h>
using namespace std;

class DisjointSet {
 public:
  int n;
  vector<int> p;
  DisjointSet() {}
  DisjointSet(int n) : n(n), p(n) {
    iota(begin(p), end(p), 0);
  }
  int Find(int x) {
    return p[x] == x ? x : p[x] = Find(p[x]);
  }
  int Unite(int x, int y) {
    x = Find(x), y = Find(y);
    if (x != y) {
      p.emplace_back(n);
      p[x] = p[y] = n;
      n++;
      return 1;
    }
    return 0;
  }
};

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0), cout.tie(0);

  int n, m;
  cin >> n >> m;
  vector<vector<pair<int, int>>> adj(n);
  for (int i = 0; i < m; i++) {
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].emplace_back(v, w);
    adj[v].emplace_back(u, w);
  }
  int k;
  cin >> k;
  vector<int> dist(n, -1);
  priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
  for (int i = 0; i < k; i++) {
    int g;
    cin >> g;
    g--;
    dist[g] = 0;
    pq.emplace(0, g);
  }

  while (!pq.empty()) {
    int u = pq.top().second;
    int d = pq.top().first;
    pq.pop();
    if (dist[u] != d) {
      continue;
    }
    for (auto e : adj[u]) {
      int v = e.first;
      int w = e.second;
      if (dist[v] == -1 || dist[v] > dist[u] + w) {
        dist[v] = dist[u] + w;
        pq.emplace(dist[v], v);
      }
    }
  }

  vector<int> order(n);
  iota(begin(order), end(order), 0);
  sort(begin(order), end(order), [&](int i, int j) { return dist[i] > dist[j]; });

  DisjointSet D(n);
  vector<int> done(n);
  vector<int> depth(n);
  vector<int> parent(n, -1);
  vector<vector<int>> tree(n);
  for (auto u : order) {
    done[u] = 1;
    for (auto v : adj[u]) {
      if (done[v.first] && D.Find(u) != D.Find(v.first)) {
        int r = tree.size();
        depth.emplace_back();
        tree.emplace_back();
        parent.emplace_back(-1);
        dist.emplace_back(dist[u]);
        tree[r].emplace_back(D.Find(u));
        tree[r].emplace_back(D.Find(v.first));
        assert(D.Unite(u, v.first));
      }
    }
  }

  vector<vector<int>> lift(tree.size(), vector<int>(20, -1));
  function<void(int)> Dfs = [&](int u) {
    lift[u][0] = parent[u];
    for (int j = 1; j < 20; j++) {
      if (lift[u][j - 1] == -1) {
        lift[u][j] = -1;
      } else {
        lift[u][j] = lift[lift[u][j - 1]][j - 1];
      }
    }
    for (auto v : tree[u]) {
      depth[v] = depth[u] + 1;
      parent[v] = u;
      Dfs(v);
      dist[u] = min(dist[u], dist[v]);
    }
  };
  Dfs(int(tree.size()) - 1);


  int q;
  cin >> q;
  while (q--) {
    int u, v;
    cin >> u >> v;
    u--, v--;
    if (depth[u] > depth[v]) {
      swap(u, v);
    }
    int diff = depth[v] - depth[u];
    for (int i = 0; i < 20; i++) {
      if (diff & (1 << i)) {
        v = lift[v][i];
      }
    }
    for (int i = 19; i >= 0; i--) {
      if (lift[u][i] != lift[v][i]) {
        u = lift[u][i];
        v = lift[v][i];
      }
    }
    if (u != v) {
      u = lift[u][0];
      v = lift[v][0];
    }
    assert(u == v);
    cout << dist[u] << '\n';
  }
  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...