luogu1351 [NOIp2014]联合权值 (dfs)
有两种情况:一个点到它的父亲的父亲(要算两次)、一个点的子节点之间互相到达
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=2e5+10,mod=10007; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 int N,v[maxn]; 16 int eg[maxn*2][2],egh[maxn],ect; 17 int fa[maxn],mans,ans; 18 19 inline void adeg(int a,int b){ 20 eg[++ect][0]=b;eg[ect][1]=egh[a];egh[a]=ect; 21 } 22 23 void dfs(int x){ 24 int mm=0; 25 if(fa[fa[x]]){ 26 mans=max(mans,v[x]*v[fa[fa[x]]]); 27 ans=(ans+v[x]*v[fa[fa[x]]]*2)%mod; 28 } 29 int sum=0; 30 for(int i=egh[x];i;i=eg[i][1]){ 31 int b=eg[i][0];if(b==fa[x]) continue; 32 sum=(sum+v[b])%mod; 33 mans=max(mans,mm*v[b]); 34 mm=max(mm,v[b]); 35 fa[b]=x;dfs(b); 36 } 37 for(int i=egh[x];i;i=eg[i][1]){ 38 int b=eg[i][0];if(b==fa[x]) continue; 39 ans=(ans+v[b]*(sum-v[b]))%mod; 40 } 41 } 42 43 int main(){ 44 //freopen(".in","r",stdin); 45 int i,j,k; 46 N=rd(); 47 for(i=1;i<N;i++){ 48 int a=rd(),b=rd(); 49 adeg(a,b);adeg(b,a); 50 } 51 for(i=1;i<=N;i++) v[i]=rd(); 52 dfs(1); 53 printf("%d %d\n",mans,(ans%mod+mod)%mod); 54 return 0; 55 }