POJ 3342 Party at Hali-Bula【树型dp好题】

来源:互联网 发布:企业网站排名怎么优化 编辑:程序博客网 时间:2024/06/05 02:57

Party at Hali-Bula

Time Limit: 2000MS

 

Memory Limit: 65536K

Total Submissions: 5989

 

Accepted: 2138

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 followingn-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

Tehran 2006

 

题目大意:有n个人参加一个party,其中直接上下级不想在同一场合出现,所以我们这里需要知道最多能够同时有多少人参加party。


思路:树型dp求最大独立集+判断取法是否唯一。


1、反向建图,从最高长官作为根节点,从这里开始向下Dfs、
2、 
我们设定dp【i】【0】表示节点i属于被邀请的一个人,其子节点问题全部解决了的情况下的最大开心值。 
我们设定dp【i】【1】表示节点i不属于被邀请的一个人,其子节点问题全部解决了的情况下的最大开心值。 
那么不难理解,max(dp【root】【0】,dp【root】【1】)就是我们要求的解。 
3、 
其中动态转移方程写出的思路: 
u是i的子节点。 
dp【i】【0】=val【i】+sum(节点i的子节点)dp【u】【1】;这里不难理解:因为节点i属于被邀请的一个人,那么其直接相连的子节点就是其当前节点的直接上下级关系,是不能够被邀请的。 
dp【i】【1】=sum(节点i的子节点)max(dp【u】【1】,dp【u】【0】);因为点i不属于被邀请的一个人,那么其相连的子节点虽然与当前节点为直接上下级关系,但是其因为当前i节点已经保证不属于被邀请的一个人了,所以其子节点的状态无所厚非,直接选其中最优的即可。 


那么我们如何判断一个图中的最大独立团是否唯一呢?我们先看这样一个图:

显而易见,dp【1】【0】==dp【1】【1】==2,那么我们不妨设想:dp【root】【0】==dp【root】【1】代表着根拿不拿都能够取得最大值2.那么也就说明,这样的情况下是不唯一的。那么我们有这样的大胆猜想:是不是如果dp【root】【0】!=dp【root】【1】就一定是唯一解呢?我们来看这样一张图:


明显dp【root】【0】=5,dp【root】【1】=4,然而仔细观察就能知道,这个图的最大独立团不唯一。直接推翻了我们刚刚的大胆设想,虽然设想不成立,但是对于第一个说法:

如果有这样的式子成立:dp【i】【0】==dp【i】【1】,那么说明以i为根节点的子树,选取的子树的最大独立团是不唯一的。

其实也就不难理解,如果有这样的式子成立,那么i的直接父节点u所构成的子树,如果父节点不是最大独立团中的一员的话,以点u构成的子树的最大独立团,当u不选取的时候,不唯一。

那么也不难理解,如果当节点i,并且i不属于最大独立团所形成的子树不唯一的时候 ,那么其父节点u,并且u属于独立团所形成的子树,也不唯一。

那么我们可以在Dfs的过程中维护这样一个数组:

judge【i】【0】其值为0表示以i为根节点,并且i属于最大独立图所形成的子树不唯一,否则唯一。

judge【i】【1】起止为0表示以i为根节点,并且i不属于最大独立团所形成的子树不唯一,否则唯一。

那么对于刚刚所述,我们可以写出推出这样的式子:


            if(dp[to][0]==dp[to][1])//如果子节点选取和不选取形成的子树的最大独立团不唯一            {                judge[now][1]=0;//那么这个点不选取的时候,所形成的子树的最大独立团也不唯一            }            if(judge[to][1]==0)//如果子节点不选取的时候不唯一。            {                judge[now][0]=0;//那么这个点选取的时候,所形成的子树的最大独立团也不唯一            }


对于其是否唯一的判断从叶子一直回溯到根,最后再判断根的种种可能就能够构建出完整的思路了。


注意的点:不要忘记数组的初始化,和输出的大小写问题。


AC代码:

#include<stdio.h>#include<string.h>#include<iostream>#include<map>#include<vector>using namespace std;vector<int >mp[500];char tmp[500];char tmp2[500];int dp[500][2];int vis[500];int judge[500][2];void Dfs(int now){    dp[now][0]=1;    dp[now][1]=0;    judge[now][0]=1;    judge[now][1]=1;    vis[now]=1;    for(int i=0;i<mp[now].size();i++)    {        int to=mp[now][i];        if(vis[to]==0)        {            Dfs(to);            dp[now][0]+=dp[to][1];            dp[now][1]+=max(dp[to][0],dp[to][1]);            if(dp[to][0]==dp[to][1])            {                judge[now][1]=0;            }            if(judge[to][1]==0)            {                judge[now][0]=0;            }        }    }}int main(){    int n;    while(~scanf("%d",&n))    {        if(n==0)break;        map< string ,int  >s;        scanf("%s",tmp);        int cont=2;        s[tmp]=1;        memset(dp,0,sizeof(dp));        memset(vis,0,sizeof(vis));        memset(judge,1,sizeof(judge));        for(int i=1;i<=n;i++)mp[i].clear();        for(int i=0;i<n-1;i++)        {            int u,v;            scanf("%s%s",tmp,tmp2);            u=s[tmp];v=s[tmp2];            if(u==0)u=cont,s[tmp]=cont,cont++;            if(v==0)v=cont,s[tmp2]=cont,cont++;            mp[v].push_back(u);        }        Dfs(1);        if(dp[1][1] > dp[1][0] && judge[1][1])            printf("%d Yes\n", dp[1][1]);        else if(dp[1][1] < dp[1][0] && judge[1][0])            printf("%d Yes\n", dp[1][0]);        else            printf("%d No\n", max(dp[1][0] , dp[1][1]));    }}/*917 12 14 18 73 29 25 46 3*/






0 0
原创粉丝点击