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
",maxans,ans);    
	return 0;
}



原文地址:https://www.cnblogs.com/cnyali/p/4163902.html