BotByte

HLD.cpp

May 3rd, 2018
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.27 KB | None | 0 0
  1. /*
  2.     Author : M. A. Rafsan Mazumder
  3.     Algorithm : Heavy Light Decomposition
  4.     Problem : SPOJ - QTREE
  5.               Given a tree with N nodes, edges are numbered 1, 2, 3, .. , n-1
  6.               1-Query : CHANGE i ti : Change the cost of the ith edge to ti
  7.               2-Query : a b : ask for the maximum edge cost on the path from node a to node b
  8. */
  9.  
  10. #include <bits/stdc++.h>
  11.  
  12. using namespace std;
  13.  
  14. #define MAX 10005
  15. #define MAX_LOG 15
  16.  
  17. vector<int> adj[MAX], costs[MAX];
  18. int n, root, subSize[MAX], par[MAX][MAX_LOG], level[MAX];
  19. int baseArray[MAX], ptr;
  20. int chainNo, chainInd[MAX], chainHead[MAX], posInBase[MAX];
  21. int chainSize[MAX], chainPos[MAX];
  22. int tree[4*MAX];
  23. pair<pair<int, int>, int> p[MAX];
  24.  
  25. void gen()
  26. {
  27.     for(int i=0; i<MAX; i++){
  28.         adj[i].clear();
  29.         costs[i].clear();
  30.         chainHead[i] = -1;
  31.         chainSize[i] = 0;
  32.         for(int j=0; j<MAX_LOG; j++) par[i][j] = -1;
  33.     }
  34.     ptr = 1;
  35.     chainNo = 1;
  36.     root = 1;
  37. }
  38.  
  39. /*
  40.  * dfs used to set parent of a node, depth of a node, subtree size of a node
  41.  */
  42.  
  43. void dfs(int u, int prev, int depth)
  44. {
  45.     par[u][0] = prev;
  46.     level[u] = depth;
  47.     subSize[u] = 1;
  48.  
  49.     for(int i=0; i<adj[u].size(); i++){
  50.         int v = adj[u][i];
  51.         if(v != prev){
  52.             dfs(v, u, depth+1);
  53.             subSize[u] += subSize[v];
  54.         }
  55.     }
  56. }
  57.  
  58. /*
  59.  * precompute 2^j the parent of ith node
  60.  */
  61.  
  62. void preComputeLCA()
  63. {
  64.     for(int j=1; j<MAX_LOG; j++){
  65.         for(int i=1; i<=n; i++){
  66.             if(par[i][j-1] != -1) par[i][j] = par[par[i][j-1]][j-1];
  67.         }
  68.     }
  69. }
  70.  
  71. /*
  72.  * LCA: Takes two nodes u, v and returns Lowest Common Ancestor of u, v
  73.  */
  74.  
  75. int LCA(int u, int v)
  76. {
  77.     if(level[u] < level[v]) swap(u, v);
  78.     int diff = level[u]-level[v];
  79.     for(int i=0; i<MAX_LOG; i++){
  80.         if((1<<i) & diff) u = par[u][i];
  81.     }
  82.     if(u == v) return u;
  83.     for(int i=MAX_LOG-1; i>=0; i--){
  84.         if(par[u][i] != par[v][i]){
  85.             u = par[u][i];
  86.             v = par[v][i];
  87.         }
  88.     }
  89.     return par[u][0];
  90. }
  91.  
  92. /*
  93.  * Actual HL-Decomposition part
  94.  * Initially all entries of chainHead[] are set to -1.
  95.  * So when ever a new chain is started, chain head is correctly assigned.
  96.  * As we add a new node to chain, we will note its position in the baseArray.
  97.  * In the first for loop we find the child node which has maximum sub-tree size.
  98.  * The following if condition is failed for leaf nodes.
  99.  * When the if condition passes, we expand the chain to special child.
  100.  * In the second for loop we recursively call the function on all normal nodes.
  101.  * chainNo++ ensures that we are creating a new chain for each normal child.
  102.  */
  103.  
  104.  /*
  105.   * chainInd[curNode] - Given a node, to which chain does that node belong to.
  106.   * chainHead[chainNo] - Given a chain, what is the head of the chain
  107.   * chainSize[chainNo] - Given a chain, what is the size of the chain
  108.   * chainPos[curNode] - Given a node, what is the position of the node in its chain
  109.   * posInBase[curNode] -  Position of this node in baseArray which we will use in Segtree
  110.   */
  111.  
  112. void HLD(int curNode, int cost, int prev)
  113. {
  114.     if(chainHead[chainNo] == -1){
  115.         chainHead[chainNo] = curNode; // Assign chain head
  116.     }
  117.     chainInd[curNode] = chainNo;
  118.     chainSize[chainNo]++;
  119.     chainPos[curNode] = chainSize[chainNo]; // 1-indexed
  120.     posInBase[curNode] = ptr; // Position of this node in baseArray which we will use in Segtree
  121.     baseArray[ptr] = cost;
  122.     ptr++;
  123.  
  124.     int sc = -1, ncost;
  125.     // Loop to find special child
  126.     for(int i=0; i<adj[curNode].size(); i++){
  127.         int v = adj[curNode][i];
  128.         if(v != prev){
  129.             if(sc == -1 || subSize[v] > subSize[sc]){
  130.                 sc = v;
  131.                 ncost = costs[curNode][i];
  132.             }
  133.         }
  134.     }
  135.  
  136.     if(sc != -1){
  137.         // Expand the chain
  138.         HLD(sc, ncost, curNode);
  139.     }
  140.  
  141.     for(int i=0; i<adj[curNode].size(); i++){
  142.         int v = adj[curNode][i];
  143.         if(v != prev && v != sc){
  144.             // New chains at each normal node
  145.             chainNo++;
  146.             HLD(v, costs[curNode][i], curNode);
  147.         }
  148.     }
  149. }
  150.  
  151. /*
  152.  * init_tree:
  153.  * Used to construct the segment tree. It uses the baseArray for construction
  154.  */
  155.  
  156. void init_tree(int node, int b, int e)
  157. {
  158.     if(b == e){
  159.         tree[node] = baseArray[b];
  160.         return;
  161.     }
  162.     int left = 2*node;
  163.     int right = 2*node+1;
  164.     int mid = (b+e)/2;
  165.     init_tree(left, b, mid);
  166.     init_tree(right, mid+1, e);
  167.     if(tree[left] > tree[right]) tree[node] = tree[left];
  168.     else tree[node] = tree[right];
  169. }
  170.  
  171. /*
  172.  * query_tree:
  173.  * Given S and E, it will return the maximum value in the range [S,E]
  174.  */
  175.  
  176. int query_tree(int node, int b, int e, int l, int r)
  177. {
  178.     if(l > e || r < b) return 0;
  179.     if(b >= l && e <= r) return tree[node];
  180.     int left = 2*node;
  181.     int right = 2*node+1;
  182.     int mid = (b+e)/2;
  183.     int q1 = query_tree(left, b, mid, l, r);
  184.     int q2 = query_tree(right, mid+1, e, l, r);
  185.     if(q1 > q2) return q1;
  186.     else return q2;
  187. }
  188.  
  189. /*
  190.  * update_tree:
  191.  * Point update. Update a single element of the segment tree.
  192.  */
  193.  
  194. void update_tree(int node, int b, int e, int pos, int val)
  195. {
  196.     if(pos > e || pos < b) return;
  197.     if(b == pos && e == pos){
  198.         tree[node] = val;
  199.         return;
  200.     }
  201.     int left = 2*node;
  202.     int right = 2*node+1;
  203.     int mid = (b+e)/2;
  204.     update_tree(left, b, mid, pos, val);
  205.     update_tree(right, mid+1, e, pos, val);
  206.     if(tree[left] > tree[right]) tree[node] = tree[left];
  207.     else tree[node] = tree[right];
  208. }
  209.  
  210. /*
  211.  * query_up:
  212.  * It takes two nodes u and v, condition is that v is an ancestor of u
  213.  * We query the chain in which u is present till chain head, then move to next chain up
  214.  * We do that way till u and v are in the same chain, we query for that part of chain and break
  215.  */
  216.  
  217.  int query_up(int u, int v)
  218.  {
  219.      if(u == v) return 0;
  220.      int uchain, vchain = chainInd[v], ans = -1;
  221.      while(1){
  222.         uchain = chainInd[u];
  223.         if(uchain == vchain){
  224.             // Both u and v are in the same chain, so we need to query from u to v, update answer and break.
  225.             // We break because we came from u up till v, we are done
  226.             if(u == v) break;
  227.             int temp = query_tree(1, 1, ptr, posInBase[v]+1, posInBase[u]);
  228.             if(temp > ans) ans = temp;
  229.             break;
  230.         }
  231.         int temp = query_tree(1, 1, ptr, posInBase[chainHead[uchain]], posInBase[u]);
  232.         if(temp > ans) ans = temp;
  233.         u = chainHead[uchain]; // move u to u's chainHead
  234.         u = par[u][0]; // Then move to its parent, that means we changed chains
  235.      }
  236.      return ans;
  237.  }
  238.  
  239.  
  240. /*
  241.  * We have a query from u to v, we break it into two queries, u to LCA(u, v) and
  242.                                                               v to LCA(u, v)
  243.  */
  244.  
  245. void query(int u, int v)
  246. {
  247.     int lca = LCA(u, v);
  248.     int ans1 = query_up(u, lca);
  249.     int ans2 = query_up(v, lca);
  250.     int ans;
  251.     if(ans1 > ans2) ans = ans1;
  252.     else ans = ans2;
  253.     printf("%d\n", ans);
  254. }
  255.  
  256. void change(int edgeNum, int val)
  257. {
  258.     int u = p[edgeNum].first.first;
  259.     int v = p[edgeNum].first.second;
  260.     int cost = p[edgeNum].second;
  261.     int node = u;
  262.     if(level[v] > level[u]) node = v;
  263.     update_tree(1, 1, ptr, posInBase[node], val);
  264. }
  265.  
  266. int main()
  267. {
  268.     //freopen("in.txt", "r", stdin);
  269.     int cases;
  270.     scanf("%d", &cases);
  271.     while(cases--){
  272.         gen();
  273.         scanf("%d", &n);
  274.         for(int i=1; i<n; i++){
  275.             int u, v, w;
  276.             scanf("%d %d %d", &u, &v, &w);
  277.             p[i] = make_pair(make_pair(u, v), w);
  278.             costs[u].push_back(w);
  279.             costs[v].push_back(w);
  280.             adj[u].push_back(v);
  281.             adj[v].push_back(u);
  282.         }
  283.         dfs(1, -1, 0);
  284.         preComputeLCA();
  285.         HLD(1, -1, -1);
  286.         ptr--;
  287.         init_tree(1, 1, ptr);
  288.         while(1){
  289.             char s[100];
  290.             scanf("%s", s);
  291.             if(s[0] == 'D') break;
  292.             int a, b;
  293.             scanf("%d %d", &a, &b);
  294.             if(s[0] == 'Q'){
  295.                 query(a, b);
  296.             }
  297.             else {
  298.                 change(a, b);
  299.             }
  300.         }
  301.     }
  302. }
  303.  
  304. /*
  305.     1
  306.  
  307.     3
  308.     1 2 1
  309.     2 3 2
  310.     QUERY 1 2
  311.     CHANGE 1 3
  312.     QUERY 1 2
  313.     DONE
  314.  
  315.     1
  316.     3
  317. */
Advertisement
Add Comment
Please, Sign In to add comment