楼教主男人八题(第二题)

今天来搞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-1n1 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,isit(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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值