[P4178] Tree-- dotted rule

(Face questions from luogu)

Title Description

Give you an TREE, as well as from the top of the tree. How many of point asked if the distance between them is less than equal to their K

Input Format

N (n <= 40000) next row n-1 sides of the pipeline is described, according to the title is written next input k

Output Format

Line, there is a distance between the pair of points is less than the number equal to k

 

  Originally dotted rule template title, last night transferred from tonight ...... here a few minutiae points to note when the government realized the next record.

1, the process of determining the partition subtree size recursively

  The following points are Kernel partition process, in which u represents cur tree root for the partition size.

  1. void Divide(int u) {   
  2.     vis[u] = true;  
  3.     ans += Solve(u, 0);  
  4.     int tcur = cur;  
  5.     for (int i = head[u]; i; i = edge[i].nxt) {  
  6.         int v = edge[i].to;  
  7.         if (vis[v]) continue;  
  8.         ans -= Solve(v, edge[i].w);  
  9.         Mn = inf;  
  10.         //cur = size[v];  
  11.         cur = size[u] > size[v] ? size[v] : tcur - size[u];  
  12.         Find_rt(v, u);  
  13.         Divide(root);  
  14.     }  
  15. }  

  Key in the first row 10, 11 sub-tree recursively determine the size of the two way, line 11 which are not annotated version is correct. Every time we take into account the root partition of the current selected tree in the center of gravity, then u is not necessarily the tree root node in the search tree sense. In other words, the child node u v u might be the father of the search tree, thus adding a special judge in determining the size of the sub-tree recursively. Because the value of cur because of previous traverse v change, we record the current size of the tree with a new variable in the fourth row. This is the source of transfer pot of the day

  (But is said without the complexity of this judgment does not deteriorate ...... it looks like there are people demonstrated, but to ensure the correctness apparently good)

2, about the pros and cons of two ways for writing dotted rule

  Dotted explain the different wording of the rule, see my blog: https: //www.cnblogs.com/TY02/p/11203163.html

  Prior to the practice of a constant with the inclusion-exclusion counted twice too large, compared to the sub-tree statistics separated from each other better. In fact, the second approach has its limitations: for example, in this problem, the violence enumerate each path will fly T, we can put all the nodes in the subtree are u depth statistical again, after ordering the use of monotonic with double pointer statistical answer. This exposed the molecular trees statistical disadvantage, it can only handle two trees do not leak to twenty-two enumeration, a combination of path information, which can not be nested in other operations. Inclusion and exclusion advantage is that all the nodes it Disposable figured out, similar to the case for the present problem by using data monotonic ordered statistics. The problem is not the sort you can also use weights Fenwick tree to do the same complexity, due to the constant empty array will be larger.

Complete code:

  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. #include <algorithm>  
  5. #define BUG puts("$$$")  
  6. #define rint register int  
  7. #define maxn 40010  
  8. typedef long long ll;  
  9. using namespace std;  
  10. const int inf = (int)1e9;  
  11. template <typename T>   
  12. void read(T &x) {  
  13.     x = 0;  
  14.     char ch = getchar();  
  15. //  int f = 1;  
  16.     while (!isdigit(ch)) {  
  17. //      if (ch == '-') f = -1;   
  18.         ch = getchar();  
  19.     }  
  20.     while (isdigit(ch)) {  
  21.         x = x * 10 + (ch ^ 48);  
  22.         ch = getchar();  
  23.     }  
  24. //  x *= f;  
  25. }  
  26. int n, k;  
  27. int years = 0;  
  28. int head[maxn], top;  
  29. struct E {  
  30.     int to, nxt, w;  
  31. } edge[maxn << 1];  
  32. inline void insert(int u, int v, int w) {  
  33.     edge[++top] = (E) {v, head[u], w};  
  34.     head[u] = top;  
  35. }  
  36. bool vis[maxn];  
  37. int size[maxn], root, Mn, cur;  
  38. void Find_rt(int u, int pre) {  
  39.     size[u] = 1;  
  40.     int Mxson = 0;  
  41.     for (int i = head[u]; i; i = edge[i].nxt) {  
  42.         int v = edge[i].to;  
  43.         if (v == pre || vis[v]) continue;  
  44.         Find_rt(v, u);  
  45.         size[u] += size[v];  
  46.         Mxson = max(Mxson, size[v]);  
  47.     }  
  48.     Mxson = max(Mxson, cur - size[u]);  
  49.     if (Mn > Mxson)  
  50.         root = u, Mn = Mxson;  
  51. }  
  52. Safety int [maxn], tot;  
  53.   
  54. void calc(int u, int pre, int d) {  
  55.     Safety [tot ++] = p;  
  56.     if (d >= k) return;  
  57.     for (int i = head[u]; i; i = edge[i].nxt) {  
  58.         int v = edge[i].to;  
  59.         if (v == pre || vis[v]) continue;  
  60.         calc (v, u, d + edge [i] .w);  
  61.     }  
  62. }  
  63. Solve you ( you and,  you extra) {  
  64.     int ret = 0;  
  65.     tot = 0;  
  66.     calc (a, 0, extra);  
  67.     Sort (Safety + 1, 1 + Safety + tot);  
  68.     Rint l = 1, r = all;  
  69.     while (l < r)  
  70.         Safety [l] + Safety [r] <= k? (RET + = (r - l), l ++): (--r);  
  71.     Return the right;  
  72. }  
  73. void Divide(int u) {  
  74.     vis[u] = true;  
  75.     ans += Solve(u, 0);  
  76.     int tcur = cur;  
  77.     for (int i = head[u]; i; i = edge[i].nxt) {  
  78.         int v = edge[i].to;  
  79.         if (vis[v]) continue;  
  80.         ans -= Solve(v, edge[i].w);  
  81.         Mn = inf;  
  82.         //cur = size[v];  
  83.         cur = size[u] > size[v] ? size[v] : tcur - size[u];  
  84.         Find_rt(v, u);  
  85.         Divide(root);  
  86.     }  
  87. }  
  88. int main () {  
  89.     read(n);  
  90.     int u, v, w;  
  91.     for (int i = 1; i < n; ++i) {  
  92.         read(u), read(v), read(w);  
  93.         insert(u, v, w), insert(v, u, w);  
  94.     }  
  95.     read(k);  
  96.     MM = inf, put = n;  
  97.     Find_rt(1, 0);  
  98.     Divide(root);  
  99.     printf("%d", ans);  
  100.     return 0;  
  101. }  

 

 

Guess you like

Origin www.cnblogs.com/TY02/p/11267061.html