P1351 联合权值(树形dp)

P1351 联合权值

想刷道水题还交了3次.....丢人

(1.没想到有两个点都是儿子的状况 2.到处乱%(大雾))

先dfs一遍处理出父亲$fa[x]$

蓝后再一遍dfs,搞搞就出来了。

#include<iostream>
#include<cstdio>
#include<cstring>
#define re register
using namespace std;
const int p=10007;
int max(int &a,int &b){return a>b?a:b;}
#define N 200002 
int n,fa[N],val[N],f1[N],f2[N];
int cnt,hd[N],nxt[N<<1],ed[N],poi[N<<1];
void adde(int x,int y){
    nxt[ed[x]]=++cnt; hd[x]=hd[x]?hd[x]:cnt;
    ed[x]=cnt; poi[cnt]=y;
}
void dfs1(int x,int ffa){//处理fa数组
    fa[x]=ffa;
    for(int i=hd[x];i;i=nxt[i])
        if(poi[i]!=ffa)
            dfs1(poi[i],x);
}
void dfs2(int x){
    int mxd=0,tot=0;
    for(int i=hd[x];i;i=nxt[i]){
        int to=poi[i];
        if(to==fa[x]) continue;
        f1[x]=max(f1[x],val[to]*mxd);
        f2[x]=1ll*(f2[x]+val[to]*tot)%p;
        mxd=max(mxd,val[to]);//以上为构成联合权值的2个点都是儿子的情况
        tot=(tot+val[to])%p;
        dfs2(to);
        f1[x]=max(f1[x],f1[to]);
        f2[x]=1ll*(f2[x]+f2[to])%p;
    }
    int g=fa[fa[x]],v=val[x]*val[g];//点x和x的爷爷构成联合权值
    f1[g]=max(f1[g],v);
    f2[g]=1ll*(f2[g]+v)%p;
}
int main(){
    scanf("%d",&n); int q1,q2; 
    for(int i=1;i<n;++i){
        scanf("%d%d",&q1,&q2);
        adde(q1,q2); adde(q2,q1);
    }
    for(int i=1;i<=n;++i) scanf("%d",&val[i]);
    dfs1(1,0); dfs2(1); f2[1]=1ll*f2[1]*2%p;//记得*2
    printf("%d %d",f1[1],f2[1]);
    return 0;
}

 

posted @ 2018-10-17 21:48  kafuuchino  阅读(155)  评论(0编辑  收藏  举报