解法:
预处理统计出每个节点与其相连的所有节点中,所有点的权值之和,与点权第一第二大的两个,
然后枚举每一个点算出包括改点的有序点对中的联合权值的最大值和联合权值的总和即可。
Code:
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define mo 10007
using namespace std;
template<typename T> void chkmax(T &x,T y){x=x>y?x:y;}
template<typename T> void read(T &num){
char c=getchar();num=0;T f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){num=(num<<3)+(num<<1)+(c^48);c=getchar();}
num*=f;
}
template<typename T> void qwq(T x){
if(x>9)qwq(x/10);
putchar(x%10+'0');
}
template<typename T> void write(T x){
if(x<0){x=-x;putchar('-');}
qwq(x);
}
int W[200010];
struct wzy{
int nxt,vertice;
}edge[400010];
int head[200010];int len=0;
inline void add_edge(int x,int y){
edge[++len].nxt=head[x];edge[len].vertice=y;head[x]=len;
return;
}
int maxx[200010][2];int sum[200010];
inline void Pretreatment(int son,int father){
for(int i=head[son];i;i=edge[i].nxt){
int nop=edge[i].vertice;
if(W[nop]>maxx[son][0]){
maxx[son][1]=maxx[son][0];maxx[son][0]=W[nop];
}else if(W[nop]>maxx[son][1]){
maxx[son][1]=W[nop];
}
sum[son]+=W[nop];sum[son]%=mo;
if(nop!=father)Pretreatment(nop,son);
}
return;
}
int max_ans=0;int sum_ans=0;
inline void solve(int son,int father){
for(int i=head[son];i;i=edge[i].nxt){
int nop=edge[i].vertice;
int pos=(maxx[nop][0]==W[son])?maxx[nop][1]:maxx[nop][0];
if(!pos)continue;
chkmax(max_ans,pos*W[son]);
sum_ans+=((sum[nop]-W[son]+mo)%mo)*(W[son]%mo);sum_ans%=mo;
}
for(int i=head[son];i;i=edge[i].nxt){
int nop=edge[i].vertice;
if(nop!=father)solve(nop,son);
}
return;
}
int main(){
int n;read(n);
rep(i,1,n-1){
int u,v;read(u);read(v);
add_edge(u,v);add_edge(v,u);
}
rep(i,1,n){read(W[i]);}
Pretreatment(1,0);
solve(1,0);
write(max_ans);putchar(' ');write(sum_ans);putchar('\n');
return 0;
}