luogu1351 [NOIp2014]联合权值 (dfs)

时间:2023-03-09 19:00:05
luogu1351 [NOIp2014]联合权值 (dfs)

有两种情况:一个点到它的父亲的父亲(要算两次)、一个点的子节点之间互相到达

 #include<bits/stdc++.h>
#define pa pair<int,int>
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=2e5+,mod=; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N,v[maxn];
int eg[maxn*][],egh[maxn],ect;
int fa[maxn],mans,ans; inline void adeg(int a,int b){
eg[++ect][]=b;eg[ect][]=egh[a];egh[a]=ect;
} void dfs(int x){
int mm=;
if(fa[fa[x]]){
mans=max(mans,v[x]*v[fa[fa[x]]]);
ans=(ans+v[x]*v[fa[fa[x]]]*)%mod;
}
int sum=;
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(b==fa[x]) continue;
sum=(sum+v[b])%mod;
mans=max(mans,mm*v[b]);
mm=max(mm,v[b]);
fa[b]=x;dfs(b);
}
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(b==fa[x]) continue;
ans=(ans+v[b]*(sum-v[b]))%mod;
}
} int main(){
//freopen(".in","r",stdin);
int i,j,k;
N=rd();
for(i=;i<N;i++){
int a=rd(),b=rd();
adeg(a,b);adeg(b,a);
}
for(i=;i<=N;i++) v[i]=rd();
dfs();
printf("%d %d\n",mans,(ans%mod+mod)%mod);
return ;
}