只有图QAQ
距离为2,边权为1,所以和同一个点相连的其它点之间都会产生联合权值,枚举60分2333
可是我们为什么要枚举呢?
若当前和节点u相连的节点的权值是wi,此时u又新加了个节点m,权值为wx,那么:
ans1为最大值,ans2为总和
ans1=max(ans1,max{wi}*wx);
ans2=ans2+w1*wx+w2*wx+...wn*wx=ans2+∑wi*wx;
我们发现,只要记录当前节点所连的点的历史最大值和历史权值之和,就可以O(1)来更新两个答案了。
不过要注意,ans2对于一组关系只计算了一次,别忘了乘2 。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int size=300010;
const int mod=10007;
int f[size],t[size];
int value[size];
int sum[size],maxn[size];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&f[i],&t[i]);
}
for(int i=1;i<=n;i++) scanf("%d",&value[i]);
int ans1=0,ans2=0;
for(int i=1;i<=n-1;i++)
{
ans1=max(ans1,max(value[f[i]]*maxn[t[i]],value[t[i]]*maxn[f[i]]));
ans2=(ans2%mod+((value[f[i]]%mod)*(sum[t[i]]%mod))%mod+((value[t[i]]%mod)*(sum[f[i]]%mod))%mod)%mod;
sum[f[i]]+=value[t[i]];
sum[t[i]]+=value[f[i]];
maxn[f[i]]=max(maxn[f[i]],value[t[i]]);
maxn[t[i]]=max(maxn[t[i]],value[f[i]]);
}
printf("%d %d",ans1,(ans2*2)%mod);
return 0;
}
/*
5
1 2
2 3
3 4
4 5
1 5 2 3 10
g++ 联合权值std.cpp -o 联合权值std.exe -Wall
*/