Tree
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 8554 | Accepted: 2545 |
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.
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.
Output
For each test case output the answer on a single line.
Sample Input
5 4 1 2 3 1 3 1 1 4 2 3 5 1 0 0
Sample Output
8
Source
可以看论文。
讲得很明白了。
写分治主要是合并的过程。
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-11-17 14:30:29 4 File Name :E:\2013ACM\专题学习\树的分治\POJ1741.cpp 5 ************************************************ */ 6 7 #include <stdio.h> 8 #include <string.h> 9 #include <iostream> 10 #include <algorithm> 11 #include <vector> 12 #include <queue> 13 #include <set> 14 #include <map> 15 #include <string> 16 #include <math.h> 17 #include <stdlib.h> 18 #include <time.h> 19 using namespace std; 20 const int MAXN = 10010; 21 const int INF = 0x3f3f3f3f; 22 struct Edge 23 { 24 int to,next,w; 25 }edge[MAXN*2]; 26 int head[MAXN],tot; 27 void init() 28 { 29 tot = 0; 30 memset(head,-1,sizeof(head)); 31 } 32 void addedge(int u,int v,int w) 33 { 34 edge[tot].to = v; edge[tot].w = w; 35 edge[tot].next = head[u];head[u] = tot++; 36 } 37 bool vis[MAXN]; 38 int size[MAXN],dep[MAXN]; 39 int le,ri; 40 int dfssize(int u,int pre) 41 { 42 size[u] = 1; 43 for(int i = head[u];i != -1;i = edge[i].next) 44 { 45 int v = edge[i].to; 46 if(v == pre || vis[v])continue; 47 size[u] += dfssize(v,u); 48 } 49 return size[u]; 50 } 51 int minn; 52 //找重心 53 void getroot(int u,int pre,int totnum,int &root) 54 { 55 int maxx = totnum - size[u]; 56 for(int i = head[u];i != -1;i = edge[i].next) 57 { 58 int v = edge[i].to; 59 if(v == pre || vis[v])continue; 60 getroot(v,u,totnum,root); 61 maxx = max(maxx,size[v]); 62 } 63 if(maxx < minn){minn = maxx; root = u;} 64 } 65 void dfsdepth(int u,int pre,int d) 66 { 67 dep[ri++] = d; 68 for(int i = head[u];i != -1;i = edge[i].next) 69 { 70 int v = edge[i].to; 71 if(v == pre || vis[v])continue; 72 dfsdepth(v,u,d+edge[i].w); 73 } 74 } 75 int k; 76 int getdep(int a,int b) 77 { 78 sort(dep+a,dep+b); 79 int ret = 0, e = b-1; 80 for(int i = a;i < b;i++) 81 { 82 if(dep[i] > k)break; 83 while(e >= a && dep[e] + dep[i] > k)e--; 84 ret += e - a + 1; 85 if(e > i)ret--; 86 } 87 return ret>>1; 88 } 89 int solve(int u) 90 { 91 int totnum = dfssize(u,-1); 92 int ret = 0; 93 minn = INF; 94 int root; 95 getroot(u,-1,totnum,root); 96 vis[root] = true; 97 for(int i = head[root];i != -1;i = edge[i].next) 98 { 99 int v = edge[i].to; 100 if(vis[v])continue; 101 ret += solve(v); 102 } 103 le = ri = 0; 104 for(int i = head[root];i != -1;i = edge[i].next) 105 { 106 int v = edge[i].to; 107 if(vis[v])continue; 108 dfsdepth(v,root,edge[i].w); 109 ret -= getdep(le,ri); 110 le = ri; 111 } 112 ret += getdep(0,ri); 113 for(int i = 0;i < ri;i++) 114 { 115 if(dep[i] <= k)ret++; 116 else break; 117 } 118 vis[root] = false; 119 return ret; 120 } 121 122 int main() 123 { 124 //freopen("in.txt","r",stdin); 125 //freopen("out.txt","w",stdout); 126 int n; 127 int u,v,w; 128 while(scanf("%d%d",&n,&k) == 2) 129 { 130 if(n == 0 && k == 0)break; 131 init(); 132 for(int i = 1;i < n;i++) 133 { 134 scanf("%d%d%d",&u,&v,&w); 135 addedge(u,v,w); 136 addedge(v,u,w); 137 } 138 memset(vis,false,sizeof(vis)); 139 printf("%d\n",solve(1)); 140 } 141 return 0; 142 }