Tree
Time Limit: 1000MS Memory Limit: 30000K
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
思路
假定选择一点1为根,那其他点到根的最短距离就有两种情况。
其一,它们在根的不同分支上,那他们的最近距离就是它们到它们的最近公共祖先的距离和。
其二,如果它们在根的同一个分支上,那么最近距离就是它们之间的距离。
我们分析到这,先求出其他点到根1点的距离用一个dfs求出,放进一个数组里a[maxn],对它排一个序,这里面任意两点只有以上两种情况,来自1同一个分支,或是不同分支,而我们求得方案数一定是来自不同分支。直接求不好求,我们可以先求出
A:a[i]+a[j] <=k的方案数(不管i,j是否来自同一个分支)这种点对是对答案有贡献的。
B:a[i]+a[j]<=k的方案数(i,j来自同一个分支)同一分支,则a[i]+a[j]不是i,j之间的真是距离。
所以代码中是先把A,B的情况同时计算了,然后减去B中的方案数。
B怎么求呢?我们只要在求a数组的过程在A的前提下加一个边的权值,这样就相当于控制i,j两条边的方向就是来自于这一条边的方向。(这里看代码细细体会)
排序时间复杂度为$O(N\log(N))$递归深度为$\log(N)$,整体时间复杂度为$O(Nlog^2(N))$
代码
1 |
|