【乱搞】noip2014联合权值

http://codevs.cn/problem/3728/
题目大意:给你一棵无根树,每个点有一个权值Wi,每条边的长度为1,对于任意一对点(u,v),如果他们两个之间的距离为2,那么会产生Wu*Wi的“联合权值”,求树上所有联合权值之和和最大的联合权值分别为多少,最后结果mod10007输出。

想当年noip2014,oi才学了三个月,上去拿了60滚粗……如果这题A了就有一等啦QwQ

这个题有各种搞法,大家爱怎么搞怎么搞,这里说一下我的做法:

首先随便找个点作为根节点,让这棵树变成一棵有根树。
然后对于每个点,分别记录它所有子节点权值的和sum1,以及它每个子节点权值的平方的和sum2,最后记录子节点中权值最大的两个子节点记录下来。

所有联合权值之和=每个节点的(sum1*sum1-sum2 + 该节点的权值×它父亲的父亲的权值×2)相加 mod 10007
最大权值=max(每个节点的权值×它父亲的父亲的权值,最大的两个子节点的权值相乘)

下面来解释为什么这样做:

联合权值之和:
设节点x的子节点分别为x1,x2,x3,……,xn,它的子节点的联合权值为
(x1·x2+x1·x3+x1·x4·……·x1·xn)+(x2·x1+x2·x3+x2·x4·……)·……·(……·xn·xn-1)
这个式子等于(x1+x2+x3……xn)^2 - x1^2 - x2^2 - x3^2 …… xn^2
但是还有爷爷节点与孙子节点的权值,所以要加上,而且由于要算两遍,所以还要乘2

最大的联合权值:
只需记录一个最大值和次大值就好了,反正不会出现最大的两个值相乘出现比别的还小的情况……最后还要特别关照下爷爷节点和孙子节点的关系……

于是这道题硬生生被我玩了树形dp……
这题还有其他好多做法吧,光看看提交中有多少比我快的就知道了……

你可能感兴趣的:(题解)