NOIP2014day1T2联合权值新版题解(优化的邻接表)
之前的解题报告无法过全部数据,因邻接表没有优化,统计权值方式也太暴力,做以下修改
1、建邻接表时加一个数组来记录每个节点的尾指针位置
2、统计每个点周围所有点权值最大的两个点
3、利用x1*y1+x1*y2+x1*y3....=x1*(y1+y2+y3+...)进行简单优化加速
程序如下,完爆官方所有数据:
#include<stdio.h> #include<stdlib.h> const int maxn=200010,mod=10007; struct edge{ int x,next; }; int w[maxn],s[maxn],last[maxn],max1[maxn],max2[maxn]; struct edge e[maxn*3]; int ans,maxans,k; void add(int u,int v){ e[++k].x=v; e[last[u]].next=k; last[u]=k; } int main(){ int i,j,m,n,u,v; scanf("%d",&n); k=n; for(i=1;i<=n;i++){ e[i].x=i; last[i]=i; } for(i=1;i<n;i++){ scanf("%d%d",&u,&v); add(u,v); add(v,u); } for(i=1;i<=n;i++)scanf("%d",&w[i]); for(i=1;i<=n;i++) for(j=e[i].next; j ;j=e[j].next){ m=w[e[j].x]; s[i]=(s[i]+m)%mod; if(m>max1[i]){ max2[i]=max1[i]; max1[i]=m; }else if(m>max2[i]) max2[i]=m; } for(int i=1;i<=n;i++) maxans=maxans>max1[i]*max2[i]?maxans:max1[i]*max2[i]; for(i=1;i<=n;i++) for(j=e[i].next; j ;j=e[j].next){ m=e[j].x; ans=(ans+w[i]*(s[m]-w[i])%mod+mod)%mod; } printf("%d %d\n",maxans,ans); return 0; }