联合权值——树上问题2014noip
联合权值
思路
枚举每一个点作为中间节点
计算出它所有儿子y的权值和sum
每个儿子的要和其他儿子算一遍联合权值,
所以是\(w[y] * (sum - w[y])\)
最大值的话顺便记录下来就行
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 400000;
int ne[N], ver[N], idx, head[N];
long long ans;
long long sum;
long long a[N];
int n;
long long res;
const int mod = 10007;
void add(int u, int v) {
ne[idx] = head[u];
ver[idx] = v;
head[u] = idx;
idx++;
}
void dfs(int x) {
long long t1 = 0, t2 = 0;
sum = 0;
for (int i = head[x]; i != -1; i = ne[i]) {
int j = ver[i];
sum = ((sum + a[j]) + mod) % mod;
if (a[j] > t1) {
t2 = t1;
t1 = a[j];
} else if (a[j] > t2) {
t2 = a[j];
}
}
ans = max(ans, (long long)t2* t1 );
for (int i = head[x]; i != -1; i = ne[i]) {
int j = ver[i];
res = (res + ((long long)(sum - a[j]) * a[j] % mod) + mod) % mod;
}
}
int main() {
memset(head, -1, sizeof(head));
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
add(b, a);
}
for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
for (int i = 1; i <= n; i++) {
dfs(i);
}
cout <<ans << ' ' << (res + mod) % mod << endl;
return 0;
}
注意:
前一个答案不用取模,要看清楚题面