联合权值
https://ac.nowcoder.com/acm/problem/16495
思路:
两个点能够存在联合权值,满足两者间的距离位2,也就是他们直接有一个共同点,如u-t-v,所以u,v存在联合权值。
再通过图可以发现,其实也就是某个点的孩子节点之间两两存在联合权值,所有我们枚举每个点,通过它的孩子节点求联合权值。
一个点的孩子节点间的联合权值最大一定是孩子节点中权值第一大和权值第二大的节点的权值乘积。所有就是求孩子节点中权值最大和权值第二大的乘积是多少。
孩子节点联合权值和可以都先求一半,最后答案*2即可。
注意最大联合权值不用取模。
#include <bits/stdc++.h>
#define ull unsigned long long
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 10007;
const int N = 3e5+7;
const ll ds = 1e15+7;
const double PI = 3.141592653589793238462643383;
using namespace std;
vector<int>a[N];
ll val[N];
ll ans = 0,mmax = 0;
void solve() {
int n,u,v;
cin >> n;
for(int i = 1; i < n; i++){
cin >> u >> v;
a[u].push_back(v);
a[v].push_back(u);
}
for(int i = 1; i <= n; i++) cin >> val[i];
for(int i = 1; i <= n; i++){
ll sum = 0;
ll mm = 0,mmm = 0;
if(a[i].size() < 2) continue;
for(int j = 0; j < a[i].size(); j++) {
ans = (ans+val[a[i][j]]*mm)%mod;
mm = (mm+val[a[i][j]])%mod;
mmax = max(mmax,mmm*val[a[i][j]]);
mmm = max(mmm,val[a[i][j]]);
}
}
cout << mmax << " " << ans*2ll%mod << endl;
}
int main() {
// int t;
// scanf("%d",&t);
// while(t--)
solve();
return 0;
}