题目链接: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. android launcher开发之图标背景以及默认配置

    1:然后我自己看了一下桌面图标的载入过程: 桌面第一次载入时是默认读取一个xml配置文件,完毕配置工作.这个配置文件在Launcher文件夹下, 路径是:\Launcher\res\xml\defau ...

  2. 499 - What's The Frequency, Kenneth?

     What's The Frequency, Kenneth?  #include <stdio.h> main() { int i; char *suffix[]= { "st ...

  3. JDBC操作数据库的学习(1)

    单单对数据库的操作,比如说MySQL,我们可以在命令行窗口中执行,但是一般是应用程序要操作数据库,因此我们应该在程序中的代码上体现对数据库的操作,那么使用程序应用如何操作数据库呢?那就要使用到数据库的 ...

  4. Linux IP代理筛选系统(shell+proxy)

    代理的用途 其实,除了抓取国外网页需要用到IP代理外,还有很多场景会用到代理: 通过代理访问一些国外网站,绕过被某国防火墙过滤掉的网站 使用教育网的代理服务器,可以访问到大学或科研院所的内部网站资源 ...

  5. 5.中文问题(自身,操作系统级别,应用软件的本身),mysql数据库备份

     第一层因素: mysql的自身的设置 mysql有六处使用了字符集.分别为:client .connection.database.results.server .system. mysql&g ...

  6. VC/MFC 使edit控件不能进行粘贴操作

    这里使用消息拦截的方法 BOOL PersonDlg::PreTranslateMessage(MSG* pMsg) { if (GetDlgItem(IDC_EDIT_USER_ID)->m_ ...

  7. Delphi代码中嵌入ASM代码(简单明了)

    前言 Delphi作为一个快速高效的开发平台,使用的人越来越多,但熟悉在Delphi代码中嵌入ASM代码的程序员我想不多,因为这方面的资料太少了,另一方面,它还需要有基本的汇编语言知识,关於汇编语言的 ...

  8. Lucene.Net 2.3.1开发介绍 —— 二、分词(五)

    原文:Lucene.Net 2.3.1开发介绍 -- 二.分词(五) 2.1.3 二元分词 上一节通过变换查询表达式满足了需求,但是在实际应用中,如果那样查询,会出现另外一个问题,因为,那样搜索,是只 ...

  9. SQL查询数据封装JavaBean对象

    public static List getListBySql(String sql, Class cls){   List list = new ArrayList();   Connection ...

  10. Swift - 将表格UITableView滚动条移动到底部

    有时我们需要通过代码自动将表格UITableView滚动条移动到尾部,只需要使用scrollToRowAtIndexPath方法即可,代码如下: 1 2 3 4 5 var secon = 1 //最 ...