面试题一则

有节点数为n的一棵树,每个节点i有一个权值w[i],节点i到节点j的距离d[i][j]定义为在树上节点i和节点j之间有多少条边。定义f(i) = sum{w[j] * d[i][j] | -1 < j < n},求min{f(i) | -1 < i < n}。 题源来自qoshi

基本思路还是树型DP,希望能根据相邻节点的f值计算出当前节点的f值。具体的思路是,如果指定了深搜的起点为0,那么每个节点都会将树上的其他节点分为两个部分,一部分是离0点近的(设为A类节点),一部分是离0点远的(设为B类节点)。

具体的状态转移,包括4个矩阵:lw[i],记录的是某个节点划分出的属于A类节点的权值和;rw[i]记录属于B类节点的权值和;lws[i]记录的是sum{ w[j] * d[i][j] | j属于i划分出的A类节点};rws[i]记录的是sum{ w[j] * d[i][j] | j属于i划分出的B类节点}。由此f(i) = lws[i] + rws[i]。使用这4个矩阵是因为,沿着某条边走一步后,某个节点的这4个值可以根据相邻节点的信息O(1)地得到。

其中rws[i],需要从自底向上的构造,也就是用了深搜遍历完所有孩子节点后,再计算父节点的值;而lws[i],则是自顶向下的计算。

具体的程序如下:

只有自己做的一些测试数据,没有找到OJ版本的题目:

输入1:

输出1:

输入2:

输出2: