标签:
题目链接:http://poj.org/problem?id=1741
树分治相关论文:http://wenku.baidu.com/view/60c6aa1ffc4ffe473368aba8.html
由于论文中有该题的讲解,所以便不再赘述。代码如下
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define lowbit(a) ((a)&(-a)) 7 #define max(a, b) ((a)>(b)?(a):(b)) 8 #define min(a, b) ((a)<(b)?(a):(b)) 9 #define MAXN 10010 10 #define MAXM 20010 11 #define PI 3.1415926 12 #define E 2.718281828 13 #define INF 0x777777f 14 typedef long long LL; 15 16 int eCnt, fir[MAXN]; struct edge{int v, w, nxt;} eg[MAXM]; 17 int n, k, ans, q[MAXN], size[MAXN], maxx[MAXN], vis[MAXN], dis[MAXN]; 18 19 void addedge(int u, int v, int w){ 20 eg[++eCnt].v = v; eg[eCnt].w = w; 21 eg[eCnt].nxt = fir[u]; fir[u] = eCnt; 22 } 23 void init(){ 24 eCnt = ans = 0; 25 for (int i = 0; i <= n; i++){ 26 vis[i] = fir[i] = 0; 27 } 28 } 29 /*找出树的重心*/ 30 int bfs_root(int u){ 31 int h = 1, t = 1, ret = 0; maxx[0] = INF; 32 q[t] = u; maxx[u] = 0; size[u] = 1; vis[u] = 2; 33 for ( ; h <= t; h++){ 34 for (int u = q[h], e = fir[u]; e != 0; e = eg[e].nxt){ 35 if (!vis[eg[e].v]){ 36 vis[eg[e].v] = 2; 37 q[++t] = eg[e].v; 38 size[eg[e].v] = 1; 39 maxx[eg[e].v] = 0; 40 } 41 } 42 } 43 for (h--; h > 0; h--){ 44 int u = q[h]; 45 vis[u] = 0; 46 for (int e = fir[u]; e != 0; e = eg[e].nxt){ 47 if (!vis[eg[e].v]){ 48 size[u] += size[eg[e].v]; 49 maxx[u] = max(maxx[u], size[eg[e].v]); 50 } 51 } 52 maxx[u] = max(t-size[u], maxx[u]); 53 if (maxx[u] < maxx[ret]) ret = u; 54 } 55 return ret; 56 } 57 /*预处理root到子节点的距离*/ 58 int dfs_dis(int u){ 59 int h = 1, t = 1; 60 q[t] = u; dis[t] = 0; vis[u] = 2; 61 for ( ; h <= t; h++){ 62 for (int u = q[h], e = fir[u]; e != 0; e = eg[e].nxt){ 63 if (!vis[eg[e].v]){ 64 vis[eg[e].v] = 2; 65 q[++t] = eg[e].v; 66 dis[t] = dis[h] + eg[e].w; 67 } 68 } 69 } 70 for (h = 1; h <= t; h++) vis[q[h]] = 0; 71 return t; 72 } 73 /*计算满足长度小于k且经过u的路径的数量,且路径可以不合法*/ 74 int dfs_calc(int u, int k){ 75 int num = dfs_dis(u), ret = 0; 76 sort(dis+1, dis+1+num); 77 for (int i = 1, j = num; i < j; i++){ 78 for ( ; dis[i] + dis[j] > k; j--) 79 if (i == j) break; 80 ret += j - i; 81 } 82 return ret; 83 } 84 /*点分治*/ 85 void dfs(int u){ 86 int root = bfs_root(u); 87 ans += dfs_calc(root, k); 88 vis[root] = 1; 89 for (int e = fir[root]; e != 0; e = eg[e].nxt){ 90 int v = eg[e].v; 91 if (vis[v]) continue; 92 ans -= dfs_calc(v, k-eg[e].w*2); 93 dfs(v); 94 } 95 } 96 int main(){ 97 int u, v, w; 98 for ( ; ; ){ 99 init(); 100 scanf("%d%d", &n, &k); 101 if (n == 0 && k == 0) break; 102 for (int i = 1; i < n; i++){ 103 scanf("%d%d%d", &u, &v, &w); 104 addedge(u, v, w); 105 addedge(v, u, w); 106 } 107 dfs(1); 108 printf("%d\n", ans); 109 } 110 return 0; 111 }
标签:
原文地址:http://www.cnblogs.com/zhu8655/p/4279755.html