传送门
解题思路
先遍历一遍树,求出size[u](节点u的所有相邻节点的点权和),和图中联合权值的最大值。
如何求最大值?
求出每个点相连的点的第一大和第二大点权,相乘后与ans取max。
再求和:
再遍历一遍树,对于每个点u,答案加上w[u]*(size[v]-w[u])。
AC代码
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<iomanip> 5 #include<cmath> 6 using namespace std; 7 const int maxn=200005; 8 const int mod=10007; 9 int n,p[maxn],cnt,w[maxn],fa[maxn]; 10 long long ans,size[maxn]; 11 struct node{ 12 int v,next; 13 }e[maxn*2]; 14 void insert(int u,int v){ 15 cnt++; 16 e[cnt].v=v; 17 e[cnt].next=p[u]; 18 p[u]=cnt; 19 } 20 void dfs(int u,int f){ 21 long long max1=0,max2=0; 22 fa[u]=f; 23 for(int i=p[u];i!=-1;i=e[i].next){ 24 if(e[i].v!=f){ 25 dfs(e[i].v,u); 26 } 27 size[u]+=w[e[i].v]; 28 if(w[e[i].v]>max2) max2=w[e[i].v]; 29 if(max2>max1) swap(max2,max1); 30 } 31 ans=max(ans,max1*max2); 32 } 33 void dfs2(int u){ 34 for(int i=p[u];i!=-1;i=e[i].next){ 35 if(e[i].v!=fa[u]) dfs2(e[i].v); 36 ans+=w[u]*(size[e[i].v]-w[u]); 37 } 38 } 39 int main(){ 40 memset(p,-1,sizeof(p)); 41 cin>>n; 42 for(int i=1;i<n;i++){ 43 int u,v; 44 scanf("%d%d",&u,&v); 45 insert(u,v); 46 insert(v,u); 47 } 48 for(int i=1;i<=n;i++) scanf("%d",&w[i]); 49 dfs(1,-1); 50 cout<<ans<<" "; 51 ans=0; 52 dfs2(1); 53 cout<<ans%mod; 54 return 0; 55 }