题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2412

题意:给定一棵关系树 , 从中选择一些点 , 使这些点均不存在亲子关系 , 最多能取多少个点 , 并且判断取法是否唯一 .

分析:如果这题没有判断唯一性,就和hdu1520一样了。设 dp[i][0] 为在以 i 为根的子树中 , 不选择点 i 最多能够选的数目 ,dp[i][1] 为选择 i 点的最多数目 .

状态转移方程 :

当 u 为叶子节点时 :

dp[u][0]=0;

dp[u][1]=1;

当 u 为非叶子节点时 :

dp[u][0]=sum(max(dp[v][0],dp[v][1]))  (v 为 u 的儿子 )

dp[u][1]=sum(dp[v][0])  (v 为u 的儿子 )

至于判断唯一性:初始化flag数组全为1,即可行的唯一的。如果父节点以下的某一节点取时不唯一了,递归上去的结果也必定不唯一。

if(dp[v][0]>dp[v][1]&&flag[v][0]==0)flag[u][0]=0;//如果取子节点v即dp[v][0]时而flag[v][0]=0;由于dp[u][0]会取dp[v][0]使得flag[u][0]也变为0,即不唯一了

else if(dp[v][1]>dp[v][0]&&flag[v][1]==0)flag[u][0]=0;;//同理取dp[v][1]时而flag[v][1]=0;由于dp[u][0]会取dp[v][1]使得flag[u][0]也变为0,即不唯一了

else if(dp[v][0]==dp[v][1])flag[u][0]=0;//不唯一的源头

if(flag[v][0]==0)flag[u][1]=0;//由于dp[u][1]必取dp[v][0],所以flag[v][0]为0的话,flag[u][1]也不唯一了。

#pragma comment(linker,"/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define N 210
#define FILL(a,b) (memset(a,b,sizeof(a)))
using namespace std;
struct edge
{
int next,v;
edge(){}
edge(int v,int next):v(v),next(next){}
}e[N*];
int head[N],tot;
int num,n;
int dp[N][],flag[N][];
void addedge(int u,int v)
{
e[tot]=edge(v,head[u]);
head[u]=tot++;
}
void dfs(int u,int fa)
{
dp[u][]=;dp[u][]=;
flag[u][]=flag[u][]=;
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v;
if(v==fa)continue;
dfs(v,u);
dp[u][]+=dp[v][];
dp[u][]+=max(dp[v][],dp[v][]);
if(dp[v][]>dp[v][]&&flag[v][]==)flag[u][]=;
else if(dp[v][]>dp[v][]&&flag[v][]==)flag[u][]=;
else if(dp[v][]==dp[v][])flag[u][]=;
if(flag[v][]==)flag[u][]=;
}
} char str[N],s1[N],s2[N];
int main()
{
while(scanf("%d",&n)&&n)
{
tot=;num=;
map<string,int>mp;
FILL(head,-);
scanf("%s",str);
mp[str]=++num;
for(int i=;i<n;i++)
{
scanf("%s%s",s1,s2);
if(mp.find(s1)==mp.end())mp[s1]=++num;
if(mp.find(s2)==mp.end())mp[s2]=++num;
addedge(mp[s1],mp[s2]);
addedge(mp[s2],mp[s1]);
}
dfs(,-);
if(dp[][]>dp[][]&&flag[][]==)
printf("%d Yes\n",dp[][]);
else if(dp[][]>dp[][]&&flag[][]==)
printf("%d Yes\n",dp[][]);
else printf("%d No\n",max(dp[][],dp[][]));
}
}

hdu2412(树形dp)的更多相关文章

  1. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  2. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  3. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  4. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  5. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

  6. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  7. POJ2342 树形dp

    原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...

  8. hdu1561 The more, The Better (树形dp+背包)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...

  9. bzoj2500: 幸福的道路(树形dp+单调队列)

    好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...

  10. BZOJ 1040 树形DP+环套树

    就是有n个点n条边,那么有且只有一个环那么用Dfs把在环上的两个点找到.然后拆开,从这条个点分别作树形Dp即可. #include <cstdio> #include <cstrin ...

随机推荐

  1. BCM wifi驱动学习

    BCMwifi驱动学习 一.wifi详解1 1.代码路径:Z:\home\stonechen\svn\TD550_X\TD550\3rdparty\wifi\BCM43362\special\bcmd ...

  2. Windows Azure 数据安全(清理和泄漏)

    免责声明:本文档中所述过程为 2012 年 1 月时起的情况,如有变更,恕不另行通知. 希望将应用程序部署到 Windows Azure 的企业客户(实际上是所有客户)最为关心的就是其数据的安全性.释 ...

  3. EasyUI - Tabs

    代码: 判断是不是已经存在,如果存在,则直接选中,否则创建新的tab. $('#tabs').tabs({ fit: true, border: false }) $('#Tree').tree({ ...

  4. 修改XPMenu让ToolButton在Down=True时正确显示

    XPMenu是一个不错的程序界面效果控件,但它也存在不少不足之处.我最近又对它作了一点修改. 原因是我在程序里有一个ToolButton,其Style=tbsButton,当Down=True时,XP ...

  5. asp.net ajax 检测用户名是否可用代码

    原文  asp.net ajax 检测用户名是否可用代码 .net ajax 检测用户名是否可用代码 <script type="text/网页特效" src="c ...

  6. CF437D(The Child and Zoo)最小生成树

    题目: D. The Child and Zoo time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  7. ContentProvider简要

    1.什么是ContentProvider  数据库在Android其中是私有的,当然这些数据包含文件数据和数据库数据以及一些其它类型的数据.  不能将数据库设为WORLD_READABLE,每一个数据 ...

  8. 嵌入式Linux常见问题

    Linux问题集 1 linux设置环境变量及保存地点 1. 显示环境变量HOME $ echo $HOME /home/terry 2. 设置一个新的环境变量WELCOME $ exportWELC ...

  9. 英特尔的VT-d技术是什么?

    VT-d技术: 我们知道对于服务器而言,很重要的一个组成部分就I/O,CPU的计算能力提升虽然可以更快地处理数据,但是前提是数据能够顺畅的到达CPU,因此,无论是存储,还是网络,以及图形卡.内存等,I ...

  10. oracle查询语句中case when的使用

    case when语句语法如下: case when  表达式  then valueA  else valueB  end; 具体使用如下: select    (case when a.colum ...