Party at Hali-Bula(树形DP+判断方案数是否唯一)

Party at Hali-Bula

 UVA - 1220 

题意: 
公司里有n(n<=200)个人形成一个树状结构, 要求尽量选多的人,但不能同时选择一个人和他的直属上司,文最多能选多少人,以及是否方案唯一。 

  1 //dp[x][0]表示不选X节点能达到的最大人数,dp[x][1]表示选x节点的最大人数 
  2 //f数组含义和dp基本一致,f[x][0]表示如果不选x节点是否方案数唯一 f[x][1]表示如果选x节点方案数是否唯一
  3 //如果f数组为1表示方案数不唯一
  4 //对于一个根节点,如果其子节点中有一个方案数不唯一则其方案数不唯一
  5  
  6 #include<iostream>
  7 #include<cstdio>
  8 #include<cstring>
  9 #include<map>
 10 #include<vector>
 11 #include<algorithm>
 12 using namespace std;
 13 vector<int>v[500];
 14 string s1,s2;
 15 map<string,int>mp;
 16 int n;
 17 int flag;
 18 int dp[500][500];
 19 int f[500][500]; 
 20 int vis[500];
 21 void dfs(int x)
 22 {
 23     
 24     dp[x][0]=0;
 25     dp[x][1]=1;
 26     vis[x]=1;
 27     for(int i=0;i<v[x].size();i++)
 28     {
 29         int to=v[x][i];
 30         if(vis[to])
 31              continue;
 32         dfs(to);
 33         //选根节点 
 34         dp[x][1]+=dp[to][0];    
 35         if(f[to][0])
 36         {
 37             f[x][1]=1;
 38         }
 39         //不选根节点 
 40         if(dp[to][0]>dp[to][1])
 41         {
 42             dp[x][0]+=dp[to][0];
 43             if(f[to][0])
 44             {
 45                 f[x][0]=1;
 46             }
 47         }
 48         else
 49         {
 50             dp[x][0]+=dp[to][1];
 51             if(f[to][1]||dp[to][0]==dp[to][1])
 52             {
 53                 f[x][0]=1;
 54             }
 55         }
 56     }
 57     return ;
 58 }
 59 int main()
 60 {
 61     while(~scanf("%d",&n)&&n)
 62     {
 63         memset(vis,0,sizeof(vis));
 64         memset(dp,0,sizeof(dp));
 65         memset(f,0,sizeof(f));
 66         for(int i=0;i<500;i++)
 67             v[i].clear();
 68         mp.clear();
 69         cin>>s1;
 70         int cnt=1;
 71         if(!mp[s1])
 72         {
 73             mp[s1]=cnt++;
 74         }
 75         n--;
 76         while(n--)
 77         {
 78             cin>>s1>>s2;
 79             if(!mp[s1])
 80             {
 81                 mp[s1]=cnt++;
 82             }
 83             if(!mp[s2])
 84             {
 85                 mp[s2]=cnt++;
 86             }
 87             v[mp[s2]].push_back(mp[s1]);
 88         }
 89         flag=0;
 90         dfs(1);
 91         printf("%d ",max(dp[1][0],dp[1][1]));
 92         if(dp[1][0]==dp[1][1])
 93         {
 94             puts("No");
 95         }
 96         else
 97         {
 98              if(dp[1][0]>dp[1][1])
 99             {
100                 if(f[1][0])
101                     cout<<"No"<<endl;
102                 else
103                     cout<<"Yes"<<endl;
104             }
105             else if(dp[1][1]>dp[1][0])
106             {
107                 if(f[1][1])
108                     cout<<"No"<<endl;
109                 else
110                     cout<<"Yes"<<endl;
111             }
112 
113         }
114     }
115 }

 

转载于:https://www.cnblogs.com/1013star/p/9942412.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值