HDU2412+树形DP

第一道树形DP

详细见分析。。

View Code
  1 #include<stdio.h>
  2 #include<string>
  3 #include<stdlib.h>
  4 #include<map>
  5 #include<algorithm>
  6 #include<iostream>
  7 using namespace std;
  8 const int maxn = 205;
  9 const int maxm = 40005;
 10 struct node{
 11     int u,v,next;
 12 }edge[ maxm ];
 13 int cnt ,head[ maxn ];
 14 map<string,int>mp;
 15 
 16 void init(){
 17     cnt = 0;
 18     memset( head,-1,sizeof( head ) );
 19     mp.clear();
 20 }
 21 
 22 void addedge( int a,int b ){
 23     edge[ cnt ].u = a;
 24     edge[ cnt ].v = b;
 25     edge[ cnt ].next = head[ a ];
 26     head[ a ] = cnt++;
 27 }
 28 
 29 int dp[ maxn ][ 2 ];//dp[i][0]:第i个节点不去聚会的最多人数,dp[i][1]:第i个节点去聚会的最多人数
 30 //dp[i][0] = sigma of sons ( max(dp[j][0],dp[j][1]) );
 31 //dp[i][1] = sigma of sons ( dp[j][0] );
 32 int dup[ maxn ][ 2 ];
 33 //dup[i][j]=0:表示对于dp[i][j]这么多人参加聚会时,方案不是独一无二的。
 34 //dup[i][j]=1:表示对于dp[i][j]这么多人参加聚会时,方案是独一无二的。
 35 //如果儿子去和不去是一样的,那么父亲不去的话,肯定存在多种方案。如果父亲去的话,维持原状。
 36 //如果儿子不去的话存在多种方案,那么父亲去的话也会存在多种方案(因为父亲的值有儿子传过来,儿子不去有多种方案说明再加上一个父亲还是有多种方案)
 37 
 38 
 39 void dfs( int now ){
 40     dp[ now ][ 0 ] = 0;
 41     dp[ now ][ 1 ] = 1;
 42 
 43     dup[ now ][0]=1;  
 44     dup[ now ][1]=1;  
 45 
 46     for( int i=head[ now ];i!=-1;i=edge[ i ].next ){
 47         int v = edge[ i ].v;
 48         dfs( v );
 49         dp[ now ][ 0 ] += max( dp[ v ][ 0 ],dp[ v ][ 1 ] );
 50         dp[ now ][ 1 ] += dp[ v ][ 0 ];
 51         
 52         if( dp[ v ][0]==dp[ v ][1] ) dup[ now ][ 0 ] =0;
 53         if( dup[ v ][0]==0 ) dup[ now ][1]=0;
 54     }
 55 }
 56 
 57 int main(){
 58     int n;
 59     while( scanf("%d",&n)==1&&n ){
 60         string s1,s2;
 61         cin>>s1;
 62         init();
 63         int pcnt = 1;
 64         mp[ s1 ] = pcnt++;
 65         int num1,num2;
 66         for( int i=0;i<n-1;i++ ){
 67             cin>>s1>>s2;
 68 
 69             if( mp[s1]==0 ){
 70                 num1 = pcnt;
 71                 mp[s1]=pcnt++;
 72             }
 73             else num1 = mp[s1];
 74 
 75             if( mp[s2]==0 ){
 76                 num2 = pcnt;
 77                 mp[s2]=pcnt++;
 78             }
 79             else num2 = mp[s2];
 80 
 81             addedge( num2,num1 );
 82         }
 83         memset( dp,0,sizeof( dp ) );
 84         dfs( 1 );//树形DP
 85         if( n==1 ){
 86             printf("1 Yes\n");
 87             continue;
 88         }
 89         /*
 90         int ans = max( dp[1][0],dp[1][1] );
 91         int flag = 1;
 92         if( dp[1][0]==dp[1][0] ) flag = -1;
 93         for( int i=2;i<maxn&&flag==1;i++ ){
 94             if( dp[i][0]==ans || dp[i][1]==ans ){
 95                 flag = -1;
 96                 break;
 97             }
 98         }
 99         if( flag==-1 ) printf("%d No\n",ans);
100         else printf("%d Yes\n",ans);
101         //不懂为什么这种方法会错。。。
102         */
103         
104         if(dp[1][0]>dp[1][1] && dup[1][0])       printf("%d Yes\n",dp[1][0]);  //yes表示是独一无二的
105         else if(dp[1][1]>dp[1][0] && dup[1][1])  printf("%d Yes\n",dp[1][1]);  
106         else                                    printf("%d No\n",max(dp[1][0],dp[1][1]));  
107         
108     }
109     return 0;
110 }
keep moving...
原文地址:https://www.cnblogs.com/xxx0624/p/3033359.html