hdu 2412 树形dp

 1 /*
 2 题目大意:一个n个节点的树,求选取一些节点(不能含有父子关系的)的最大数量,且是否唯一。
 3 dp(i,0)表示当前节点i不选,dp(i,1)表示当前节点i选
 4 叶子节点dp(i,0)=0,dp(i,1)=1
 5 dp(i,0)=sigma(max(dp(j,0),dp(j,1))) (j是i的儿子)
 6 dp(i,1)=sigma(dp(j,0))+1(j是i的儿子)
 7 最多人数为max(dp(0,0),dp(0,1))(0表示根节点)
 8 用flag数组标记结果是否唯一
 9 对于叶子结点, flag[k][0]=flag[k][1] = 1.
10 对于非叶子结点,
11 不选i,对于i的任一儿子j,
12 若(dp[j][0] > dp[j][1] 且 flag[j][0] == 0) 或 (dp[j][0] < dp[j][1] 且 flag[j][1] == 0) 或 (dp[j][0] == dp[j][1]),
13 则flag[i][0] = 0
14 选i,对于i的任一儿子j有flag[j][0] = 0,
15 则flag[i][1] = 0
16 */
17 #pragma warning (disable:4786)
18 #include <iostream>
19 #include <cstring>
20 #include <cstdio>
21 #include <string>
22 #include <map>
23 #include <vector>
24 using namespace std;
25
26 const int maxn=205;
27 vector<int> f[maxn];//关系图
28 bool flag[maxn][2];//标记是否唯一
29 map<string,int> m;//名字与节点标号映射
30 int dp[maxn][2];
31 inline int max(int a,int b){return a>b?a:b;}
32
33 void dfs(int id)
34 {
35     if(f[id].size()==0)
36     {
37         dp[id][0]=0;dp[id][1]=1;
38         return ;
39     }
40     int i,sum1=0,sum2=0;
41     for(i=0;i<f[id].size();i++)
42     {
43         dfs(f[id][i]);
44         sum1+=max(dp[f[id][i]][0],dp[f[id][i]][1]);
45         sum2+=dp[f[id][i]][0];
46         if((dp[f[id][i]][0]>dp[f[id][i]][1] && flag[f[id][i]][0]==0)
47         || (dp[f[id][i]][0]<dp[f[id][i]][1] && flag[f[id][i]][1]==0)
48         || dp[f[id][i]][0]==dp[f[id][i]][1])
49             flag[id][0]=0;
50         if(flag[f[id][i]][0]==0)
51             flag[id][1]=0;
52     }
53     dp[id][0]=sum1;dp[id][1]=sum2+1;
54     return ;
55 }
56 int main()
57 {
58     int i,n,cnt;
59     string name1,name2;
60     while(scanf("%d",&n),n)
61     {
62         for(i=1;i<maxn;i++) f[i].clear();
63         m.clear();
64         cnt=0;
65         cin>>name1;m[name1]=++cnt;
66         for(i=2;i<=n;i++)
67         {
68             cin>>name1>>name2;
69             if(m.find(name1)==m.end())
70                 m[name1]=++cnt;
71             if(m.find(name2)==m.end())
72                 m[name2]=++cnt;
73             f[m[name2]].push_back(m[name1]);
74         }
75         memset(flag,1,sizeof(flag));
76         dfs(1);
77         int ans=max(dp[1][0],dp[1][1]);
78         printf("%d ",ans);
79         if(dp[1][0]==dp[1][1] || (dp[1][0]>dp[1][1] && flag[1][0]==0) || (dp[1][0]<dp[1][1] && flag[1][1]==0))
80             printf("No\n");
81         else printf("Yes\n");
82     }
83     return 0;
84 }
时间: 2024-08-20 11:13:49

hdu 2412 树形dp的相关文章

hdu 4123 树形DP+RMQ

http://acm.hdu.edu.cn/showproblem.php?pid=4123 Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the route. There are N houses and N - 1 roads in his village. Each road connects two houses,

hdu 1250 树形DP

Anniversary party Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Appoint description:  System Crawler  (2014-07-27) Description There is going to be a party to celebrate the 80-th Anniversary of the Ural St

hdu 4276(树形dp)

题意:带权树上有起点终点每个点上有宝藏,一个人只有T分钟要从起点到重点,问你最多能收集多少宝藏. 思路:树形dp,首先判断能不能走到终点,然后把路径上的边权变为0时间减去所有边权.dp[v][j]表示从v出发回到v话费j分钟最多能收集到的宝藏. dp[v][j] = max(dp[v][j], dp[x][k] + dp[v][j-k-2*val]); 被G++卡了好长时间,换成c++就过了. 代码如下: 1 #include <stdio.h> 2 #include <string.h

hdu 5148 树形dp+分组背包问题

http://acm.hdu.edu.cn/showproblem.php?pid=5148 Problem Description Long long ago,there is a knight called JayYe.He lives in a small country.This country is made up of n cities connected by n-1 roads(that means it's a tree).The king wants to reward Ja

HDU 1520 树形dp裸题

1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define max(a,b) a>b?a:b using nam

hdu 3586 树形dp+二分

题目大意:给定n个敌方据点,1为司令部,其他点各有一条边相连构成一棵 树,每条边都有一个权值cost表示破坏这条边的费用,叶子节点为前线.现要切断前线和司令部的联系,每次切断边的费用不能超过上限limit,问切断所 有前线与司令部联系所花费的总费用少于m时的最小limit.1<=n<=1000,1<=m<=100万 题目要问的是最小的最大限制,必然二分答案 然后对于每一个值,树形DP判定是否可行 dp[i]表示要切断以i为根的其它所有子树的最小代价. 其中设定叶子结点的代价为无穷大

HDU 1561 树形DP入门

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6011    Accepted Submission(s): 3555 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物

hdu 1561 树形dp

又一道树形dp,发现其实树形dp长得都挺像的. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int INF = -9999999; 7 const int N = 201; 8 int dp[N][N]; 9 int head[N]; 10 int value[N]; 11 int n, m, e; 12 13 void i

hdu 1011 树形dp+背包

题意:有n个房间结构可看成一棵树,有m个士兵,从1号房间开始让士兵向相邻的房间出发,每个房间有一定的敌人,每个士兵可以对抗20个敌人,士兵在某个房间对抗敌人使无法走开,同时有一个价值,问你花费这m个士兵可以得到的最大价值是多少 分析:树形dp,对于点u,dp[u][j]表示以u为根的树消耗j个士兵得到的最大值,dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[son][k]+val[u]) 注意是无向图,vis位置不能随便放,且注意dp不能直接+val,因为这样根节点就加不