online|hdu5834Magic boy Bi Luo with his excited tree

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5834
题意:给定一棵树,有点权和边权,点权上的价值只能取一次,多次通过边要花费多次边权,求以每个节点为起点能获得的最大价值。
分析:比较经典的一类树形dp,设1为根设g[i][0/1]表示从i出发只向儿子走的最大收获,0表示最终回到了i,1表示最终是在某个子孙中结束的,设f[i][0/1]表示i到i的父亲这条边走了两次和一次的最大收获,最终答案就是max(g[i][0]+f[i][1],g[i][1]+f[i][0])。
代码:

#include #include #include #include #include #include #include #include #include #include #include #include #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int N=100010; const int mod=1000000007; const int MOD1=1000000007; const int MOD2=1000000009; const double EPS=0.00000001; typedef long long ll; const ll MOD=1000000007; const int INF=1000000010; const ll MAX=1ll<<55; const double eps=1e-5; const double inf=~0u>>1; const double pi=acos(-1.0); typedef double db; typedef unsigned int uint; typedef unsigned long long ull; int tot,u[N],v[2*N],w[2*N],pre[2*N]; void add(int x,int y,int z) { v[tot]=y; w[tot]=z; pre[tot]=u[x]; u[x]=tot++; v[tot]=x; w[tot]=z; pre[tot]=u[y]; u[y]=tot++; } int q[N],fa[N],g1[N],g[N][2],f[N][2]; void dfs1(int x,int y) { g[x][0]=g[x][1]=q[x]; g1[x]=x; fa[x]=y; for (int i=u[x]; i!=-1; i=pre[i]) if (v[i]!=y) { dfs1(v[i],x); g[x][1]=max(g[x][1],g[x][1]+g[v[i]][0]-2*w[i]); if (g[x][0]+g[v[i]][1]-w[i]>g[x][1]) g1[x]=v[i]; g[x][1]=max(g[x][1],g[x][0]+g[v[i]][1]-w[i]); g[x][0]+=max(0,g[v[i]][0]-2*w[i]); } } void dfs2(int x,int y,int z) { f[x][0]=f[x][1]=0; if (g[x][0]<=2*z) { f[x][0]=max(f[x][0],f[y][0]+g[y][0]-2*z); f[x][1]=max(f[x][1],f[y][1]+g[y][0]-z); } else { f[x][0]=max(f[x][0],f[y][0]+g[y][0]-g[x][0]); f[x][1]=max(f[x][1],f[y][1]+g[y][0]-g[x][0]+z); } if (g1[y]==x) { int i,mx0=q[y],mx1=q[y]; for (i=u[y]; i!=-1; i=pre[i]) if (v[i]!=fa[y]&&v[i]!=x) { mx1=max(mx1,mx1+g[v[i]][0]-2*w[i]); mx1=max(mx1,mx0+g[v[i]][1]-w[i]); mx0+=max(0,g[v[i]][0]-2*w[i]); } f[x][1]=max(f[x][1],mx1+f[y][0]-z); } else { if (g[x][0]<=2*z) f[x][1]=max(f[x][1],f[y][0]+g[y][1]-z); else f[x][1]=max(f[x][1],f[y][0]+g[y][1]-g[x][0]+z); } for (int i=u[x]; i!=-1; i=pre[i]) if (v[i]!=y) dfs2(v[i],x,w[i]); } int main() { int i,n,t,x,y,z,ca; scanf("%d", &t); f[0][0]=f[0][0]=0; g[0][0]=g[0][1]=0; for (ca=1; ca<=t; ca++) { scanf("%d", &n); tot=0; memset(u,-1,sizeof(u)); for (i=1; i<=n; i++) scanf("%d", &q[i]); for (i=1; i



    推荐阅读