ssoj4009: 秀秀的森林(forest)

时间限制: 1 Sec 内存限制: 512 MB
提交: 46 解决: 17
[提交][状态][博客][加入收藏]
题目描述
秀秀有一棵带
n
n个顶点的树
T
T,每个节点有一个点权
a
i
ai。

有一天,她想拥有两棵树,于是她从
T
T中删去了一条边。

第二天,她认为三棵树或许会更好一些。因此,她又从她拥有的某一棵树中删去了一条边。

如此往复,每一天秀秀都会删去一条尚未被删去的边,直到她得到由
n
n棵只有一个点的树构成的森林。

秀秀定义一条简单路径(节点不重复出现的路径)的权值为路径上所有点的权值之和,一棵树的直径为树上权值最大的简单路径。秀秀认为树最重要的特征就是它的直径。所以她想请你算出任一时刻她拥有的所有树的直径的乘积。因为这个数可能很大,你只需输出这个数对
10
9
+
7
109+7取模之后的结果即可。

输入
输入的第一行包含一个整数
n
n,表示树
T
T上顶点的数量。

下一行包含
n
n个空格分隔的整数
a
i
ai,表示顶点的权值。

之后的
n

1
n−1行中,每一行包含两个用空格分隔的整数
u
i
ui和
v
i
vi,表示节点
u
i
ui和
v
i
vi之间连有一条边,编号为
i
i。

再之后
n

1
n−1行中,每一行包含一个整数
k
j
kj,表示在第
j
j天里会被删除的边的编号。

输出

n
n行,在第
i
i行,输出删除
n

1
n−1条边之后,所有树直径的乘积对
10
9
+
7
109+7取模的结果。

样例输入
3
1 2 3
1 2
1 3
2
1
样例输出
6
9
6
提示
样例解释

初始时,树的直径为6(由节点2、1 和3 构成的路径)。在第一天之后,得到了两棵直径都为3 的树。第二天之后,得到了三棵直径分别为1,2,3 的树,乘积为6。

数据范围 n,a[i]<=1e5

题解:
对于在树上拆分、询问的问题,直接模拟操作肯定不好做,故考虑离线,转化为加边的问题。那么考虑加一条边,即将两棵树合并为一棵树,已知两颗树上的最长链,要求合并后的最长链。考虑如何利用两棵树的最长链高效算出。发现最长链只可能是两颗子树分别的最长链或经过这条边的最长链,即这条边两端点的最长半链的和,最长半链端点一定在最长链上,故分讨即可。

猜你喜欢

转载自blog.csdn.net/sz_165394732/article/details/83549470