很有意思的一道树形DP。关键在于变量的设置。根据翻转的性质,我们设dp[ i ][ 0 ]代表以 i 为根的子树like 比 candle多多少,dp[ i ][ 1 ]则表示以 i 为根的子树like 比 candle少多少。所以每次翻转都是dp[ i ][ 0 ]和dp[ i ][ 1 ]的转换。很有意思!
#include "iostream" #include "cstdio" #include "cstring" #include "algorithm" using namespace std; int head[50005],c; struct NODE { int v,s,p; } point[50005]; struct node { int to,next; } edge[100000]; int n,X,Y; int dp[50005][2]; void dfs(int x) { if(!x) dp[x][0]=0; else dp[x][0]=point[x].v,dp[x][1]=-point[x].v; int i,to,j,k; for(i=head[x]; i!=-1; i=edge[i].next) { to=edge[i].to; dfs(to); dp[x][0]+=dp[to][0]; dp[x][1]+=dp[to][1]; } if(x) { if(point[x].s) { swap(dp[x][0],dp[x][1]); k=Y; } else k=X; dp[x][0]=max(dp[x][0],dp[x][1]-k); dp[x][1]=max(dp[x][1],dp[x][0]-k); } } int main() { int i,j,k; int v,f,s,p; while(~scanf("%d %d %d",&n,&X,&Y)) { for(i=0; i<=n; i++) head[i]=-1,dp[i][0]=0,dp[i][1]=0; for(i=1,c=0; i<=n; i++) { scanf("%d %d %d %d",&point[i].v,&f,&point[i].s,&point[i].p); edge[c].to=i,edge[c].next=head[f],head[f]=c++; if(point[i].p) point[i].v=-point[i].v; } dfs(0); if(dp[0][0] < 0) printf("HAHAHAOMG\n"); else printf("%d\n",dp[0][0]); } }
原文:http://blog.csdn.net/alone_l/article/details/20220309