POJ 1741 Tree(树的分治)
Description
Give a tree with n vertices,each edge has a length(positive integer less than 1001).
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
Input
The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.
The last test case is followed by two zeros.
The last test case is followed by two zeros.
Output
For each test case output the answer on a single line.
题目大意:给一个带边权的树,问有多少对点满足dist(i,j)<=k
思路:可以参考2009年的国家集训队论文《分治算法在树的路径问题中的应用》——漆子超。
代码(188MS):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 7 const int MAXN = 10010; 8 const int MAXE = 20010; 9 const int INF = 0x7fff7fff; 10 11 int head[MAXN], size[MAXN], maxSize[MAXN]; 12 int list[MAXN], cnt; 13 bool del[MAXN]; 14 int to[MAXE], next[MAXE], cost[MAXE]; 15 int n, k, ecnt; 16 17 void init() { 18 memset(head, -1, sizeof(head)); 19 memset(del, 0, sizeof(del)); 20 ecnt = 0; 21 } 22 23 void add_edge(int u, int v, int c) { 24 to[ecnt] = v; cost[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++; 25 to[ecnt] = u; cost[ecnt] = c; next[ecnt] = head[v]; head[v] = ecnt++; 26 } 27 28 void dfs1(int u, int f) { 29 size[u] = 1; 30 maxSize[u] = 0; 31 for(int p = head[u]; ~p; p = next[p]) { 32 int &v = to[p]; 33 if(v == f || del[v]) continue; 34 dfs1(v, u); 35 size[u] += size[v]; 36 maxSize[u] = max(maxSize[u], size[v]); 37 } 38 list[cnt++] = u; 39 } 40 41 int get_root(int u, int f) { 42 cnt = 0; 43 dfs1(u, f); 44 int ret, maxr = INF; 45 for(int i = 0; i < cnt; ++i) { 46 int &x = list[i]; 47 if(max(maxSize[x], size[u] - size[x]) < maxr) { 48 ret = x; 49 maxr = max(maxSize[x], size[u] - size[x]); 50 } 51 } 52 return ret; 53 } 54 55 void dfs2(int u, int f, int dis) { 56 list[cnt++] = dis; 57 for(int p = head[u]; ~p; p = next[p]) { 58 int &v = to[p]; 59 if(v == f || del[v]) continue; 60 dfs2(v, u, dis + cost[p]); 61 } 62 } 63 64 int calc(int a, int b) { 65 int j = b - 1, ret = 0; 66 for(int i = a; i < b; ++i) { 67 while(list[i] + list[j] > k && i < j) --j; 68 ret += j - i; 69 if(j == i) break; 70 } 71 return ret; 72 } 73 74 int ans = 0; 75 76 void work(int u, int f) { 77 int root = get_root(u, f); 78 del[root] = true; 79 int last = 0; cnt = 0; 80 for(int p = head[root]; ~p; p = next[p]) { 81 int &v = to[p]; 82 if(del[v]) continue; 83 dfs2(v, root, cost[p]); 84 sort(list + last, list + cnt); 85 ans -= calc(last, cnt); 86 last = cnt; 87 } 88 list[cnt++] = 0; 89 sort(list, list + cnt); 90 ans += calc(0, cnt); 91 for(int p = head[root]; ~p; p = next[p]) { 92 int &v = to[p]; 93 if(del[v]) continue; 94 work(v, root); 95 } 96 } 97 98 int main() { 99 while(scanf("%d%d", &n, &k) != EOF) { 100 if(n == 0 && k == 0) break; 101 init(); 102 for(int i = 1; i < n; ++i) { 103 int u, v, c; 104 scanf("%d%d%d", &u, &v, &c); 105 add_edge(u, v, c); 106 } 107 ans = 0; 108 work(1, 0); 109 printf("%d\n", ans); 110 } 111 }