树形DP(1)-Hdu 2412 Party at Hali-Bula

2024-05-10 16:32
文章标签 dp hdu 树形 party hali bula 2412

本文主要是介绍树形DP(1)-Hdu 2412 Party at Hali-Bula,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2014 寒假第一章 - 树形DP

之前做的时候没来得及上传,今天整理一下,一并上传了。首先是这道题 Party at Hali-Bula,和hdu 1520 Anniversary party 还有 1054 strategic game 很相似,不过有所加强,那两道题在之前的博客里已经讲过了,可以先写一下那两道题,想比较一下几个题的异同的,可以点这里。

下面来看这道题:

Party at Hali-Bula

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1605    Accepted Submission(s): 544


Problem Description
Dear Contestant,

I'm going to have a party at my villa at Hali-Bula to celebrate my retirement from BCM. I wish I could invite all my co-workers, but imagine how an employee can enjoy a party when he finds his boss among the guests! So, I decide not to invite both an employee and his/her boss. The organizational hierarchy at BCM is such that nobody has more than one boss, and there is one and only one employee with no boss at all (the Big Boss)! Can I ask you to please write a program to determine the maximum number of guests so that no employee is invited when his/her boss is invited too? I've attached the list of employees and the organizational hierarchy of BCM.

Best,
--Brian Bennett

P.S. I would be very grateful if your program can indicate whether the list of people is uniquely determined if I choose to invite the maximum number of guests with that condition.


Input
The input consists of multiple test cases. Each test case is started with a line containing an integer n (1 ≤ n ≤ 200), the number of BCM employees. The next line contains the name of the Big Boss only. Each of the following n-1 lines contains the name of an employee together with the name of his/her boss. All names are strings of at least one and at most 100 letters and are separated by blanks. The last line of each test case contains a single 0.


Output
For each test case, write a single line containing a number indicating the maximum number of guests that can be invited according to the required condition, and a word Yes or No, depending on whether the list of guests is unique in that case.


Sample Input
  
6 Jason Jack Jason Joe Jack Jill Jason John Jack Jim Jill 2 Ming Cho Ming 0


Sample Output
  
4 Yes 1 No


Source
2006 Asia Regional Tehran



题意: 给出n个人的直接上下级关系,形成一颗关系树,要求参加party时,下属不能和他的唯一直接上司一起去,问做多能去多少人?还有问 去最多人的 分配方式是否唯一。

分析:DP,用dp[i][0]表示 不选择i点,i点及其子树能选出的最大人数,dp[i][1]表示选择i点时,i点及其子树能选的最大人数。

状态转移方程:

1,叶子结点k:dp[k][0] = 0; dp[k][1] = 1;

2,非叶子节点i,:dp[i][1] = 1 + sigma(dp[j][0]);       dp[i][0] = sigma(max(dp[j][0],dp[j][1]))       ( j是i的儿子 )。

最多人数即 max(dp[0][1],dp[0][0]);

那么如何判断最优解是否唯一?

新加一个状态 uniq[i][2];表示在i点 取或不取是否唯一; 为1表示唯一,为0表示不唯一。

状态转移:

1.叶子结点:uniq[i][0] = uniq[1] = 1;

2:非叶子节点:

对于 i 的任一儿子 j :<1>.如果有uniq[j][0] == 0,则 uniq[i][1] = 0.

<2>如果 (dp[j][0] > dp[j][1] && uniq[j][0]==0)或(dp[j][0] < dp[j][1] && uniq[j][1]==0)或(dp[j][0] == dp[j][1])则dp[i][0] = 0.


代码:

#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define MAX 205
bool uniq[MAX][2];//用于判断是否是唯一解
int dp[MAX][2];
bool visit[MAX];
char name[MAX][105],name2[MAX][105];
vector<int> v[MAX];
int n;
void read()
{for (int i = 0; i < n; i++){dp[i][0] = 0;dp[i][1] = 1;uniq[i][0] = uniq[i][1] = 1;visit[i] = 0;v[i].clear();}char tmp[105] = {NULL};scanf("%s",name[0]);for (int i = 1; i < n; i++){scanf("%s %s",name[i],name2[i]);		}for (int i = 1; i < n; i++){for (int j = 0; j < n; j++){if(strcmp(name2[i],name[j])==0){v[i].push_back(j);v[j].push_back(i);break;}}		}
}
void solve(int u)
{visit[u] = 1;for (int i = 0; i < v[u].size(); i++){int m = v[u][i];if(visit[m] == 0){solve(m);//if(dp[m][0] > dp[m][1] && uniq[m][0] == 0)uniq[u][0]=0;else if(dp[m][1] > dp[m][0] && uniq[m][1] == 0)uniq[u][0]=0;else if(dp[m][0] == dp[m][1])uniq[u][0] = 0;if(uniq[m][0] == 0)uniq[u][1] = 0;//dp[u][1] += dp[m][0];dp[u][0] += max(dp[m][0],dp[m][1]);}}
}
int main()
{while(scanf("%d",&n)!=EOF && n!=0){		read();solve(0);printf("%d ",max(dp[0][0],dp[0][1]));if((dp[0][0]>dp[0][1] && uniq[0][0]==1) ||(dp[0][1]>dp[0][0]&&uniq[0][1]==1)){puts("Yes");}else puts("No");}return 0;
}




这篇关于树形DP(1)-Hdu 2412 Party at Hali-Bula的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/976967

相关文章

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu4865(概率DP)

题意:已知前一天和今天的天气概率,某天的天气概率和叶子的潮湿程度的概率,n天叶子的湿度,求n天最有可能的天气情况。 思路:概率DP,dp[i][j]表示第i天天气为j的概率,状态转移如下:dp[i][j] = max(dp[i][j, dp[i-1][k]*table2[k][j]*table1[j][col] )  代码如下: #include <stdio.h>#include

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

usaco 1.1 Broken Necklace(DP)

直接上代码 接触的第一道dp ps.大概的思路就是 先从左往右用一个数组在每个点记下蓝或黑的个数 再从右到左算一遍 最后取出最大的即可 核心语句在于: 如果 str[i] = 'r'  ,   rl[i]=rl[i-1]+1, bl[i]=0 如果 str[i] = 'b' ,  bl[i]=bl[i-1]+1, rl[i]=0 如果 str[i] = 'w',  bl[i]=b

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while