Advertisement
Yarodash

Heavy-Light decomposition

Jan 25th, 2020
188
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.40 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <limits>
  4.  
  5. using namespace std;
  6.  
  7. struct edge{
  8.     int v;
  9.     int w;
  10. };
  11.  
  12. struct p_edge{
  13.     int u;
  14.     int w;
  15. };
  16.  
  17. vector<p_edge> parent;
  18. vector<vector<edge>> edges;
  19. vector<int> chains;
  20. vector<int> s;
  21. vector<vector<int>> pathes;
  22. vector<int> global;
  23. vector<int> tree;
  24. vector<vector<int>> up;
  25. vector<int> tin, tout;
  26. int timer = 0;
  27. vector<int> position;
  28.  
  29. int n, N = 1, l = 1;
  30.  
  31. int calc_size(int u){
  32.     int _size = 1;
  33.     for (int i = 0; i < edges[u].size(); i++){
  34.         _size += calc_size(edges[u][i].v);
  35.     }
  36.     s[u] = _size;
  37.     return _size;
  38. };
  39.  
  40. void hl_dfs(int u, int chain){
  41.     if (chain == -1){
  42.         chain = pathes.size();
  43.         pathes.emplace_back();
  44.     }
  45.  
  46.     chains[u] = chain;
  47.     pathes[chain].push_back(u);
  48.  
  49.     if (edges[u].size() == 0)
  50.         return;
  51.  
  52.     int v_max = 0, v_index;
  53.     for (int i = 0; i < edges[u].size(); i++){
  54.         if (s[edges[u][i].v] > v_max){
  55.             v_max = s[edges[u][i].v];
  56.             v_index = edges[u][i].v;
  57.         }
  58.     }
  59.  
  60.     hl_dfs(v_index, chain);
  61.     for (int i = 0; i < edges[u].size(); i++)
  62.         if (edges[u][i].v != v_index)
  63.             hl_dfs(edges[u][i].v, -1);
  64. }
  65.  
  66. void build_global_chain(){
  67.     int p = 0;
  68.     for (int i = 0; i < pathes.size(); i++){
  69.         for (int j = 0; j < pathes[i].size(); j++){
  70.             int v = pathes[i][j];
  71.             if (v == 0) {
  72.                 position[v] = 0;
  73.                 global[p++] = -1;
  74.             } else {
  75.                 position[v] = p;
  76.                 global[p++] = parent[v].w;
  77.             }
  78.         }
  79.     }
  80. }
  81.  
  82. void build_tree_up(int index, int value){
  83.     tree[index] = value;
  84.     if (!value) return;
  85.  
  86.     int parent = (index-1)/2;
  87.     if (tree[parent] < tree[index])
  88.         build_tree_up(parent, value);
  89. }
  90.  
  91. void build_tree(){
  92.     for (int i = 0; i < n; i++)
  93.         build_tree_up(i+N-1, global[i]);
  94. }
  95.  
  96. void dfs(int v, int p = 0){
  97.     tin[v] = ++timer;
  98.     up[v][0] = p;
  99.     for (int i = 1; i < l; i++)
  100.         up[v][i] = up[up[v][i-1]][i-1];
  101.     for (int i = 0; i < edges[v].size(); i++)
  102.         dfs(edges[v][i].v, v);
  103.     tout[v] = ++timer;
  104. }
  105.  
  106. bool upper(int u, int v){
  107.     return (tin[u] <= tin[v] && tout[u] >= tout[v]);
  108. }
  109.  
  110. int lca(int a, int b){
  111.     if (upper(a, b)) return a;
  112.     if (upper(b, a)) return b;
  113.  
  114.     for (int i = l-1; i >= 0; i--){
  115.         if (!upper(up[a][i], b)){
  116.             a = up[a][i];
  117.         }
  118.     }
  119.     return up[a][0];
  120. }
  121.  
  122. int find_on_path(int chain, int v){
  123.     int l = 0, r = pathes[chain].size()-1, m;
  124.     while (r-l > 1){
  125.         m = (l+r)/2;
  126.         if (pathes[chain][m] > v) r = m;
  127.             else l = m;
  128.     }
  129.     if (pathes[chain][r] == v) return r;
  130.     if (pathes[chain][l] == v) return l;
  131.     return -1;
  132. }
  133.  
  134. int get_maximum_on_path(int v, int _lca){
  135.     int chain = chains[v];
  136.     int bottom = find_on_path(chain, v);
  137.     int top = find_on_path(chain, _lca);
  138.     bool flag = !(top == -1);
  139.  
  140.     if (bottom == top)
  141.         return std::numeric_limits<int>::min();
  142.  
  143.     bottom = N-1+position[pathes[chain][bottom]];
  144.     top    = N-1+position[pathes[chain][top+1]];
  145.  
  146.     int maximum = tree[top];
  147.  
  148.     while (top != bottom){
  149.         if (bottom/2 > top) {
  150.             if (bottom%2 == 1){
  151.                 maximum = max(maximum, tree[bottom]);
  152.                 bottom--;
  153.             } else
  154.                 bottom = (bottom-1)/2;
  155.         } else {
  156.             if (top%2 == 0){
  157.                 maximum = max(maximum, tree[top]);
  158.                 top++;
  159.             } else
  160.                 top = (top-1)/2;
  161.  
  162.         }
  163.     }
  164.     maximum = max(maximum, tree[top]);
  165.  
  166.     if (flag) return maximum;
  167.     return max(maximum, get_maximum_on_path(parent[pathes[chain][0]].u, _lca));
  168. }
  169.  
  170. int get_maximum_between(int a, int b){
  171.     int _lca = lca(a, b);
  172.     return max(get_maximum_on_path(a, _lca),
  173.                get_maximum_on_path(b, _lca)
  174.                );
  175. }
  176.  
  177. void dump_global_chain(){
  178.     for (int i = 0; i < global.size(); i++)
  179.         cout << global[i] << " ";
  180.     cout << endl;
  181. }
  182.  
  183. void dump_sizes(){
  184.     for (int i = 0; i < s.size(); i++)
  185.         cout << s[i] << " ";
  186.     cout << endl;
  187. }
  188.  
  189. void dump_chains(){
  190.     for (int i = 0; i < pathes.size(); i++){
  191.         cout << "Path #" << i + 1 << ": " << pathes[i][0];
  192.         for (int j = 1; j < pathes[i].size(); j++)
  193.             cout << " -> " << pathes[i][j];
  194.         cout << endl;
  195.     }
  196. }
  197.  
  198. int main()
  199. {
  200.     cin >> n;
  201.     while (N < n) { N *= 2; l++; };
  202.  
  203.     s.resize(n, 0);
  204.     edges.resize(n);
  205.     chains.resize(n, 0);
  206.     global.resize(n, 0);
  207.     parent.resize(n);
  208.     tree.resize(2*N, std::numeric_limits<int>::min());
  209.     tin.resize(n, 0);
  210.     tout.resize(n, 0);
  211.     position.resize(n, 0);
  212.  
  213.     up.resize(n);
  214.     for (int i = 0; i < n; i++)
  215.         up[i].resize(l, 0);
  216.  
  217.     // u - parent
  218.     int u, v, w = 0;
  219.     edge e;
  220.     p_edge p;
  221.     for (int i = 1; i < n; i++){
  222.         cin >> u >> v >> w;
  223.         e.v = v; e.w = w;
  224.         p.u = u; p.w = w;
  225.         edges[u].push_back(e);
  226.         parent[v] = p;
  227.     }
  228.     parent[0].u = -1;
  229.     parent[0].w = -1;
  230.  
  231.     calc_size(0);
  232.     hl_dfs(0, -1);
  233.  
  234.     build_global_chain();
  235.     build_tree();
  236.     dfs(0);
  237.  
  238.     dump_sizes();
  239.     dump_chains();
  240.     dump_global_chain();
  241.  
  242.     int q, r;
  243.     while (true){
  244.         cin >> q >> r;
  245.         cout << get_maximum_between(q, r) << endl;
  246.     }
  247.  
  248.     return 0;
  249. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement