树形dp(A - Anniversary party HDU - 1520 )
题目链接:https://cn.vjudge.net/contest/277955#problem/A
题目大意:略
具体思路:刚开始接触树形dp,说一下我对这个题的初步理解吧,首先,我们从根节点开始,往下dfs,dp[i][0]代表我当前的i点不要去舞会,那么对于他的孩子节点,我们是肯定不能去舞会的,所以dp[i][0]=dp[i][0]+max(dp[son][0],dp[son][1])(注意一个上司可能有多个下属,所以需要累加),这个的具体意思是如果当前的父亲节点不去的话,我们可以选择他的子节点去或者不去都行,我们只需要求出一个最大的加上就可以了。dp[i][1]代表当前的i节点,我们选择去参加舞会,所以他的子节点就肯定去不了了。所以dp[i][1]=dp[i][1]+dp[son][1]. (这道题是多组输入,竟然还卡vector)
AC代码:
1 #include<iostream> 2 #include<cmath> 3 #include<stack> 4 #include<stdio.h> 5 #include<algorithm> 6 #include<queue> 7 #include<vector> 8 #include<cstring> 9 using namespace std; 10 # define inf 0x3f3f3f3f 11 # define ll long long 12 const int maxn = 6000+100; 13 int dp[maxn][5],cost[maxn],num; 14 int father[maxn],head[maxn]; 15 struct node 16 { 17 int to; 18 int nex; 19 node() {} 20 node(int xx,int yy) 21 { 22 to=xx; 23 nex=yy; 24 } 25 } edge[maxn]; 26 void addedge(int fr,int to){ 27 edge[num].to=to; 28 edge[num].nex=head[fr]; 29 head[fr]=num++; 30 } 31 void dfs(int t) 32 { 33 dp[t][0]=0; 34 dp[t][1]=cost[t]; 35 for(int i=head[t]; i!=-1; i=edge[i].nex) 36 { 37 int u=edge[i].to; 38 dfs(u); 39 dp[t][1]+=dp[u][0]; 40 dp[t][0]+=max(dp[u][0],dp[u][1]); 41 } 42 } 43 int main() 44 { 45 int n; 46 while(~scanf("%d",&n)) 47 { 48 num=0; 49 for(int i=1; i<=n; i++) 50 { 51 head[i]=-1; 52 father[i]=i; 53 scanf("%d",&cost[i]); 54 } 55 int t1,t2; 56 for(int i=1; i<=n; i++) 57 { 58 scanf("%d %d",&t1,&t2); 59 if(t1==0&&t2==0) 60 break; 61 addedge(t2,t1); 62 father[t1]=t2; 63 } 64 int ed=1; 65 while(ed!=father[ed]) 66 ed=father[ed]; 67 dfs(ed); 68 printf("%d\n",max(dp[ed][1],dp[ed][0])); 69 } 70 return 0; 71 } 72 73