标签:
题意:求树上距离不超过k的点对数
解决:很经典的树分治
1 //#include <bits/stdc++.h> 2 #include <iostream> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cstring> 6 7 const int MAXN = 10000+10; 8 9 struct Edge{ 10 int u, v, cost, next; 11 Edge(){} 12 Edge(int u, int v, int cost, int next) 13 { 14 this->u = u; 15 this->v = v; 16 this->cost = cost; 17 this->next = next; 18 } 19 }edge[MAXN<<1]; 20 int tot; 21 int head[MAXN]; 22 int dist[MAXN]; 23 int siz[MAXN]; 24 int max_sub[MAXN]; 25 int root; 26 int res; 27 bool vis[MAXN]; 28 int n, k; 29 int min_max_siz; 30 int sort_size; 31 32 void addEdge(int u, int v, int cost) 33 { 34 edge[++tot] = Edge(u, v, cost, head[u]); 35 head[u] = tot; 36 } 37 38 void init() 39 { 40 tot = 1; 41 memset(head, 0, sizeof head); 42 res = 0; 43 memset(vis, false, sizeof vis); 44 } 45 46 void getRoot(int u, int fa, int r) 47 { 48 if (siz[r] - siz[u] > max_sub[u]) { 49 max_sub[u] = siz[r] - siz[u]; 50 } 51 if (min_max_siz > max_sub[u]) { 52 min_max_siz = max_sub[u]; 53 root = u; 54 } 55 for (int i = head[u]; i > 0; i = edge[i].next) { 56 int v = edge[i].v; 57 if (v != fa && vis[v] == false) { 58 getRoot(v, u, r); 59 } 60 } 61 } 62 63 void getSize(int u, int fa) 64 { 65 siz[u] = 1; max_sub[u] = 0; 66 for (int i = head[u]; i > 0; i = edge[i].next) { 67 int v = edge[i].v; 68 if (v != fa && vis[v] == false) { 69 getSize(v, u); 70 siz[u] += siz[v]; 71 if (siz[v] > max_sub[u]) { 72 max_sub[u] = siz[v]; 73 } 74 } 75 } 76 } 77 78 void getDist(int u, int fa, int d) 79 { 80 dist[++sort_size] = d; 81 for (int i = head[u]; i > 0; i = edge[i].next) { 82 int v = edge[i].v; 83 if (v != fa && vis[v] == false) { 84 getDist(v, u, d + edge[i].cost); 85 } 86 } 87 } 88 89 int calc(int u, int d) 90 { 91 int ret = 0; 92 sort_size = 0; 93 getDist(u, 0, d); 94 std::sort(dist+1, dist+1+sort_size); 95 for (int i = 1; ; ++ i) { 96 int val = k - dist[i]; 97 // get the first position where dist[pos] lager than val 98 // then pos-1 is the right most position 99 // where dist[pos-1] is less than or equal to val 100 int pos = std::upper_bound(dist+1, dist+sort_size+1, val) - dist; 101 -- pos; 102 if (pos <= i) { 103 break; 104 } 105 ret += (pos-i); 106 } 107 return ret; 108 } 109 110 void dfs(int u) 111 { 112 min_max_siz = n; 113 // 1 array siz[]: sizes of all subtree 114 // 2 array sub_max[]: the max subtree of each node 115 getSize(u, 0); 116 // 117 getRoot(u, 0, u); 118 res += calc(root, 0); 119 vis[root] = true; 120 for (int i = head[root]; i > 0; i = edge[i].next) { 121 int v = edge[i].v; 122 if (vis[v] == false) { 123 res -= calc(v, edge[i].cost); 124 dfs(v); 125 } 126 } 127 128 } 129 130 int main() 131 { 132 while (~scanf("%d%d", &n, &k)) { 133 if(!(n||k)) { 134 break; 135 } 136 init(); 137 for (int i = 1; i <= n-1; ++ i) { 138 int u, v, cost; 139 scanf("%d%d%d", &u, &v, &cost); 140 addEdge(u, v, cost); 141 addEdge(v, u, cost); 142 } 143 dfs(1); 144 printf("%d\n", res); 145 } 146 return 0; 147 }
标签:
原文地址:http://www.cnblogs.com/takeoffyoung/p/4741754.html