1 条题解
-
0
楼上大佬的淀粉质小蒟蒻不会(哭)。
那就来一篇十分简短(但是不易懂?)的题解吧!
推式子
首先我们可以发现,这张图有 个节点和 ,所以这张图实际上是一棵无根树,两点之间有唯一路径。
对于每一对 ,必然会有一点(就叫 吧)在这两点之间。
所以对于每一个点 ,可产生联合权值:
( 是与 相邻的点的个数)
化简亿下:
$$\begin{aligned} \sum\limits_{i=1}^m\sum\limits_{j=1}^m{w_i}{w_j} &=\sum\limits_{i=1}^m({w_i\sum\limits_{j=1}^m}{w_j}) \newline &=(\sum\limits_{i=1}^m{w_i})(\sum\limits_{j=1}^m{w_j}) \newline &=(\sum\limits_{i=1}^m{w_i})^2 \end{aligned}$$Clever OIer 肯定都看出来了:
照这么算,肯定会出现 。
辣么,把多算的减掉就好了!
式子变成:
$$(\sum\limits_{i=1}^m{w_i})^2-(\sum\limits_{i=1}^m{w_i^2})$$把所有的 遍历一遍加起来,式子变成:
$$\sum\limits_{k=1}^n((\sum\limits_{i=1}^{m_k}{w_i})^2-(\sum\limits_{i=1}^{m_k}{w_i^2}))$$大功告成!
哦对,还有 最大值!
对于每个 ,找一下与之相连的最大的 和 乘一下再和
ans比个大小就好了!Code!
#include <bits/stdc++.h> #define __Made return #define in 0 #define China__ ; using namespace std; int n; int u, v; vector<int> mp[200005]; long long w[200005]; long long ans1, ans2; void solve(int x) { long long max1 = 0, max2 = 0; long long sum1 = 0, sum2 = 0; for(auto i : mp[x]) { if(w[i] >= max1) max2 = max1, max1 = w[i]; else if(w[i] >= max2) max2 = w[i]; sum1 += w[i]; sum2 += w[i] * w[i]; } ans1 = max(ans1, max1 * max2); ans2 += sum1 * sum1 - sum2; ans2 %= 10007; } int main() { scanf("%d", &n); for(int i = 1; i <= n - 1; i++) { scanf("%d %d", &u, &v); mp[u].push_back(v); mp[v].push_back(u); } for(int i = 1; i <= n; i++) scanf("%lld", &w[i]); for(int i = 1; i <= n; i++) solve(i); printf("%lld %lld", ans1, ans2); __Made in China__ }
- 1
信息
- ID
- 57
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 9
- 标签
- 递交数
- 10
- 已通过
- 9
- 上传者