Advertisement
Guest User

Centroid Decomposition

a guest
Nov 21st, 2020
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.85 KB | None | 0 0
  1. // Accepted code for https://acm.timus.ru/problem.aspx?space=1&num=1471
  2. #include <algorithm>
  3. #include <iostream>
  4. #include <vector>
  5.  
  6. using namespace std;
  7.  
  8. const int N = 1e5 + 10;
  9. const int LOGN = 20;
  10. // Original Tree
  11. vector<int> g[N];
  12. int sub[N], nn, U[N], V[N], W[N], deleted[N];
  13. // Centroid Tree
  14. int par[N], level[N], dist[LOGN][N];
  15. // dist[LOGN][N] : dist[lvl][x] :  Distance between C and x in the original tree, when node C becomes a centroid at level "lvl".
  16. // G[u] --> [v1, v2, v3] ... Not doing this.
  17. // G[u] --> [e1, e1, e3 ..]
  18. int adj(int x, int e) { return U[e] ^ V[e] ^ x; }
  19. void dfs1(int u, int p) {
  20.   sub[u] = 1;
  21.   nn++;
  22.   for (auto e : g[u]) {
  23.     int w = adj(u, e);
  24.     if (w != p && !deleted[e]) dfs1(w, u), sub[u] += sub[w];
  25.   }
  26. }
  27. int find_centroid(int u, int p) {
  28.   for (auto e : g[u]) {
  29.     if (deleted[e]) continue;
  30.     int w = adj(u, e);
  31.     if (w != p && sub[w] > nn / 2) return find_centroid(w, u);
  32.   }
  33.   return u;
  34. }
  35. void add_edge_centroid_tree(int parent, int child) {
  36.   par[child] = parent;
  37.   level[child] = level[parent] + 1;
  38. }
  39. void dfs2(int u, int p, int lvl) {
  40.   for (auto e : g[u]) {
  41.     int w = adj(u, e);
  42.     if (w == p || deleted[e]) continue;
  43.     dist[lvl][w] = dist[lvl][u] + W[e];
  44.     dfs2(w, u, lvl);
  45.   }
  46. }
  47. // unordered_map<int, int> dist[N]; -- inefficient.
  48. // all the nn nodes which lie in the component of "centroid"
  49. // dist[centroid][x] = <value>
  50. // int dist[LOGN][N]; (centroid,x) --> one to one mapping --> (level[centroid], x);
  51. void decompose(int root, int p = -1) {
  52.   nn = 0;
  53.   // Compute subtree sizes and no. of nodes (nn) in this tree.
  54.   dfs1(root, root);
  55.   // Find the centroid of the tree and make it the new root.
  56.   int centroid = find_centroid(root, root);
  57.   // Construct the Centroid Tree
  58.   if (p == -1) p = root;
  59.   add_edge_centroid_tree(p, centroid);
  60.   // Process the O(N) paths from centroid to all leaves in this component.
  61.   dfs2(centroid, centroid, level[centroid]);
  62.   // Delete the adjacent edges and recursively decompose the adjacent subtrees.
  63.   for (auto e : g[centroid]) {
  64.     if (deleted[e]) continue;
  65.     deleted[e] = 1;
  66.     int w = adj(centroid, e);
  67.     decompose(w, centroid);
  68.   }
  69. }
  70.  
  71. int compute_distance(int x, int y) {
  72.   // We need to compute the LCA(x, y) in the centroid tree.
  73.   // O(logN).
  74.   int lca_level = 0;
  75.   for (int i = x, j = y; (lca_level = level[i]) && i != j;
  76.        level[i] < level[j] ? (j = par[j]) : (i = par[i]))
  77.     ;
  78.   return dist[lca_level][x] + dist[lca_level][y];
  79. }
  80.  
  81. int main() {
  82.   int n;
  83.   scanf("%d", &n);
  84.   for (int i = 1; i < n; i++) {
  85.     scanf("%d %d %d", U + i, V + i, W + i);
  86.     U[i]++;
  87.     V[i]++;
  88.     g[U[i]].push_back(i);
  89.     g[V[i]].push_back(i);
  90.   }
  91.   decompose(1);
  92.   int m;
  93.   scanf("%d", &m);
  94.   while (m--) {
  95.     int x, y;
  96.     scanf("%d %d", &x, &y);
  97.     printf("%d\n", compute_distance(x + 1, y + 1));
  98.   }
  99. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement