【2015.9.6】JZOJ4211送你一颗圣诞树

题目大意

有n+1棵树,第一棵为一个点,编号0
从i=1~n读入a,b,c,d,l表示用权值为l的边连接Tree a的点c和Tree b的点d,对每一棵树,输出树里面的点两两之间的距离
即ans[i]=这里写图片描述,d为点i,j的距离

数据范围:
对于30% 的数据,m <= 8
对于60% 的数据,m <= 16
对于100% 的数据,1 <= m<= 60,T<= 100

分析

不难发现ans_i由几个部分相加得来:
1、ans[Tree a]+ans[Tree b];
2、size[Tree a]*size[Tree b]*l(在求距离的过程中,新边一共被累加了size[Tree a]*size[Tree b]次,因为对于所有i属于Tree a,j属于Tree b,i,j之间的路径上一定有新边l);
3、Tree a中所有点到c点的距离*size[b]+Tree b中所有点到d点的距离*size[a];

而对于前两种情况,都可以用记录下来,在需要用到的时候直接累加;
第三种情况中,以Tree a为例:
若c在a的第一棵子树上,则所求的值就是第二棵子树上所有点到c的距离和+第一棵子树上所有点到c的距离和;
于是前者可以转化成第二棵子树上左右点到d(这个d是连接这棵树时的关键点,不是d_i)的距离+l(连接这棵树时的新边)+c_i到c(这个c是连接这棵树时的关键点,不是c_i);前者和后者都可以递归实现。

代码略O(∩_∩)O~~

PS:由于搜索量较大,需要用到记忆化搜索。C++选手可以用map容器,Pascal选手就要打hash了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值