[noip2014day1-T2]联合权值

无向连通图 G 有 n 个点,n-1 条边。点从 1 到 n 依次编号,编号为 i 的点的权值为 Wi,每条边的长度均为 1。图上两点(u, v)的距离定义为 u 点到 v 点的最短距离。对于图 G 上的点对(u, v),若它们的距离为 2,则它们之间会产生Wu*Wv的联合权值。
请问图 G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少?

 

题解:树形dp;

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iomanip>
#include<map>
#include<set>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long 
using namespace std;
#define LL long long 
#define up(i,j,n) for(int i=(j);(i)<=(n);(i)++)
#define max(x,y) ((x)<(y)?(y):(x))
#define min(x,y) ((x)<(y)?(x):(y))
#define FILE "1"
const int maxn=202000,mod=10007;
int read(){
    int x=0;bool flag=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')flag=1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
    return flag?-x:x;
}
int n;

struct node{
    int y,next;
}e[maxn<<1];
int linkk[maxn],len=0,w[maxn],maxx[maxn];
int Max=0,Sum=0;
void insert(int x,int y){
    e[++len].y=y;
    e[len].next=linkk[x];
    linkk[x]=len;
}
void init(){
    n=read();
    int x,y;
    up(i,2,n){
        x=read(),y=read();
        insert(x,y);insert(y,x);
    }
    up(i,1,n)w[i]=read();
}
int q[maxn],tail,head=0,fa[maxn],siz[maxn],ans[maxn],ru[maxn];
void bfs(){
    head=tail=0;
    q[++tail]=1;int x;
    while(++head<=tail){
        x=q[head];
        for(int i=linkk[x];i;i=e[i].next){
            if(e[i].y==fa[x])continue;
            ru[x]++;
            fa[e[i].y]=x;
            q[++tail]=e[i].y;
        }
    }
    tail=0,head=0;
    up(i,1,n)if(!ru[i])q[++tail]=i;
    while(++head<=tail){
        x=q[head];
        ans[x]=(ans[x]+w[fa[x]]*siz[x])%mod;
        Sum+=ans[x];
        if(--ru[fa[x]]==0)q[++tail]=fa[x];
        ans[fa[x]]=(ans[fa[x]]+siz[fa[x]]*w[x])%mod;
        siz[fa[x]]=(siz[fa[x]]+w[x])%mod;
        Sum=(Sum+ans[x])%mod;
        if(w[x]*maxx[fa[x]]>Max)Max=w[x]*maxx[fa[x]];
        if(w[fa[x]]*maxx[x]>Max)Max=w[fa[x]]*maxx[x];
        if(w[x]>maxx[fa[x]])maxx[fa[x]]=w[x];
    }
    cout<<Max<<" "<<Sum<<endl;
}
int main(){
    freopen(FILE".in","r",stdin);
    freopen(FILE".out","w",stdout);
    init();
    bfs();
}
View Code

 

posted @ 2016-10-11 13:20  CHADLZX  阅读(133)  评论(0编辑  收藏  举报