P1351 联合权值(树形dp)
想刷道水题还交了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; }