
今天来搞1741 Tree
男人进度:2/8

题目链接
http://poj.org/problem?id=1741
题目描述
Give a tree with nnn vertices,each edge has a length(positive integer less than 1001).
The defination of dist(u,v)dist(u,v)dist(u,v) is The min distance between node uuu and vvv.
Give an integer kkk,for every pair (uuu,vvv) of vertices is called valid if and only if dist(u,v)dist(u,v)dist(u,v) not exceed kkk.
Write a program that will count how many pairs which are valid for a given tree.
输入
The input contains several test cases.
The first line of each test case contains two integers nnn, kkk. (n<=10000) The following n−1n-1n−1 lines each contains three integers uuu,vvv,lll, which means there is an edge between node uuu and vvv of length lll.
The last test case is followed by two zeros.
输出
For each test case output the answer on a single line.
样例输入
5 4 1 2 3 1 3 1 1 4 2 3 5 1 0 0
样例输出
8
样例解释

样例给出的树如上图示,共有8条符合要求的边:
- 1->2,距离为 3
- 1->3,距离为 1
- 1->4,距离为 2
- 1->3->5,距离为 1+1=2
- 2->1->3,距离为 3+1=4
- 3->5,距离为 1
- 3->1->4,距离为 1+2=3
- 4->1->3->5,距离为 2+1+1=4
题解
知识点:树的重心
因为题目给出的是无向边,那么把哪个节点当作根节点都无所谓了。那么不妨设有一棵以节点1为根的树,长成下面这个样子:

仔细观察,我们可以依据是否包含根节点,把路径分为两类:
- 包含根节点(比如 1->2,4->1->5)
- 不包含根节点(比如 2->3, 5->6)
不难发现,不包含的根节点的路径,其所包含的节点必然都来自于同一棵子树。这就很符合递归的要求了,为了描述清楚,我们不妨先设:
- 以节点iii 为根的子树的合法路径总数为 t(i)t(i)t(i)
- 以节点iii 为根的子树的包含节点iii的合法路径总数为 f(i)f(i)f(i)
t(i)t(i)t(i) 可以递归的定义为:
t(i)={
0,i是叶子∑s是i的儿子t(s)+f(i),i不是叶子 t(i)= \begin{cases} 0, i是叶子 \\ \sum_{s是i的儿子} t(s) + f(i), i不是叶子 \end{cases} t(i)={
0,i是叶子∑s是i的儿子t(s)+f(i),i不是叶子
问题简化了,答案可表示为t(1)=∑i=1nf(i)t(1) = \sum_{i=1}^{n} f(i)t(1)=∑i=1nf(i)。那么如何求解 f(i)f(i)f(i) 咧?

对于每个节点 iii,做对应子树遍历,计算出该子树中每个节点和节点 iii 的距离。

比如有上面这样一棵树,为了方便,我们不妨设边的权值都为 1。那么每棵子树上的节点到对应根节点的距离如下图示:

需要注意的是,真实场景中的权值并不相等,若想得到关于距离升序的数组,不得不进行一次排序。
不管怎么说,现在我们得到 nnn 个距离的数组。我们不妨设距离的限制为 KKK。
现在对于每个数组,进行一次双指针遍历操作:
- 首先指针 lll 指向第一个元素,指针 rrr 指向最后一个元素,累加器 sum = 0。
- 接着下述两个步骤,直到 l=rl = rl=r
- 如果 l+r<=Kl+r <= Kl

最低0.47元/天 解锁文章
1290

被折叠的 条评论
为什么被折叠?



