Submission #790136

#TimeUsernameProblemLanguageResultExecution timeMemory
790136tch1cherinValley (BOI19_valley)C++17
100 / 100
1659 ms124260 KiB
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx2")
#include <bits/stdc++.h>
using namespace std;
 
const int N = 1e5 + 5;
const int L = __lg(N) + 2;
vector<tuple<int, int, int>> g[N];
int dp[L][N], ancestors[N][L], depth[N], edges[N][3], sz[N], cnt[N];
long long weight[L][N], dp_down[N], dp_up[N], dp_val[N], dist[N];
bool used[N], has_shop[N];
unordered_map<int, long long> min_excluding[N];
 
void build_lifting(int u = 0, int p = 0) {
  dp[0][u] = p;
  depth[u] = p == 0 ? 0 : depth[p] + 1;
  for (int i = 1; i < L; i++) {
    dp[i][u] = dp[i - 1][dp[i - 1][u]];
    weight[i][u] = weight[i - 1][u] + weight[i - 1][dp[i - 1][u]];
  }
  for (auto [i, v, w] : g[u]) {
    if (v != p) {
      weight[0][v] = w;
      build_lifting(v, u);
    }
  }
}
 
long long dis(int u, int v) {
  if (depth[u] < depth[v]) {
    swap(u, v);
  }
  long long ans = 0;
  for (int i = L - 1; i >= 0; i--) {
    if (depth[u] - (1 << i) >= depth[v]) {
      ans += weight[i][u];
      u = dp[i][u];
    }
  }
  if (u == v) {
    return ans;
  }
  for (int i = L - 1; i >= 0; i--) {
    if (dp[i][u] != dp[i][v]) {
      ans += weight[i][u] + weight[i][v];
      u = dp[i][u], v = dp[i][v];   
    }
  }
  ans += weight[0][u] + weight[0][v];
  return ans;
}
 
bool check(int a, int b, int i) {
  return min(dis(a, edges[i][0]) + dis(edges[i][1], b), dis(b, edges[i][0]) + dis(a, edges[i][1])) + edges[i][2] == dis(a, b); 
}
 
void sizes(int u, int p) {
  sz[u] = 1;
  for (auto [i, v, w] : g[u]) {
    if (v != p && !used[v]) {
      sizes(v, u);
      sz[u] += sz[v];
    }
  }
}
 
int centroid(int u, int p, int n) {
  for (auto [i, v, w] : g[u]) {
    if (v != p && !used[v] && sz[v] > n / 2) {
      return centroid(v, u, n);
    }
  }
  return u;
}
 
void DFS1(int u, int p, int c) {
  ancestors[u][cnt[u]++] = c;
  dp_down[u] = has_shop[u] ? dist[u] : LLONG_MAX;    
  for (auto [i, v, w] : g[u]) {
    if (v != p && !used[v]) {
      dist[v] = dist[u] + w;
      DFS1(v, u, c);
      dp_down[u] = min(dp_down[u], dp_down[v]); 
    }
  }
}
 
void DFS2(int u, int p, int c) {
  long long Min = LLONG_MAX, Smin = LLONG_MAX;
  for (auto [i, v, w] : g[u]) {
    if (!used[v]) {
      Smin = min(Smin, dp_down[v]);
      if (Smin < Min) {
        swap(Smin, Min);
      }
    }
  }
  for (auto [i, v, w] : g[u]) {
    if (v != p && !used[v]) {
      auto tmp1 = dp_down[u], tmp2 = dp_down[v];
      dp_down[u] = min(has_shop[u] ? dist[u] : LLONG_MAX, dp_down[v] == Min ? Smin : Min);
      dp_down[v] = min(dp_down[v], dp_down[u]);
      min_excluding[c][i] = dp_down[u];
      DFS2(v, u, c);
      dp_down[u] = tmp1;
      dp_down[v] = tmp2;
    } 
  } 
}
 
void _build_centroids(int u) {
  sizes(u, -1);
  dist[u] = 0;
  DFS1(u, -1, u);
  dp_val[u] = dp_down[u];
  dp_up[u] = has_shop[u] ? 0 : LLONG_MAX;
  DFS2(u, -1, u);
  used[u] = true;
  for (auto [i, v, w] : g[u]) {
    if (!used[v]) {
      int C = centroid(v, u, sz[v]);
      _build_centroids(C);
    }
  }
}
 
void build_centroids() {
  memset(ancestors, -1, sizeof ancestors);
  memset(used, 0, sizeof used);
  memset(cnt, 0, sizeof cnt);
  sizes(0, -1);
  _build_centroids(centroid(0, -1, sz[0]));
}
 
void solve() {
  int n, s, q, e;
  cin >> n >> s >> q >> e;
  e--;
  for (int i = 0; i < n - 1; i++) {
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    edges[i][0] = u, edges[i][1] = v, edges[i][2] = w;
    g[u].emplace_back(i, v, w);
    g[v].emplace_back(i, u, w);
  }
  for (int i = 0; i < s; i++) {
    int C;
    cin >> C;
    has_shop[--C] = true;
  }
  build_lifting();
  build_centroids();
  while (q--) {
    int I, R;
    cin >> I >> R;
    I--, R--;
    if (!check(R, e, I)) {
      cout << "escaped\n";
    } else {
      long long ans = LLONG_MAX;
      for (int i = 0; i < cnt[R]; i++) {
        if (!check(R, ancestors[R][i], I)) {
          long long x;
          if (!min_excluding[ancestors[R][i]].count(I)) {
            x = dp_val[ancestors[R][i]];
          } else {
            x = min_excluding[ancestors[R][i]][I];
          }
          if (x != LLONG_MAX) {
            ans = min(ans, dis(ancestors[R][i], R) + x); 
          } 
        }
      }
      if (ans == LLONG_MAX) {
        cout << "oo\n";
      } else {
        cout << ans << "\n";
      }
    }
  }
}
 
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  solve();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...