# UVA - 1220

UVA - 1220

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.

题意

举行一场宴会要邀请公司里的一些员工,这个公司里面每一个人(除了打老板)有且只有一个老板,邀请的原则是不能同时邀请他和他的老板,输出最大邀请数,如果在最大邀请数下,邀请方案唯一则输出YES 反之,输出 NO。

思路

首先需要对输入中的名字做数字化处理(map),并且建树,存好父节点和子节点(vector),树形dp,开一个二维的dp,后面一位用于存储当前位的状态(是否邀请当前位),然后就是状态转移方程的推理,如果邀请了当前位,那么他的子节点一定不能邀请,如果没有邀请当前位那么他的子节点是可以邀请也可以不邀请的。另一个需要注意到的是方案唯一性的判断,如果存在一个节点,邀请或者不邀请时,向上传递的答案相同时,可知方案不唯一。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e2 + 5;
map<string, int> s;
vector<int > vi[maxn];
int dp[maxn][2];
bool flag[maxn][2];
void dfs(int u)
{
    int len = vi[u].size();
    for(int i = 0; i < len; i++)
    {
        int v = vi[u][i];
        dfs(v);
        dp[u][0] += max(dp[v][1], dp[v][0]);
       	dp[u][1] += dp[v][0];
 		 if((dp[v][0]>dp[v][1]&&!flag[v][0])
 		 ||(dp[v][0]<dp[v][1]&&!flag[v][1])
 		 ||dp[v][0]==dp[v][1])
                 flag[u][0]=false;
         if(!flag[v][0]) 
                 flag[u][1]=false;
    }
}

int main()
{
    int n;
    while(scanf("%d", &n) != EOF, n)
    {
        s.clear();
        memset(dp,0,sizeof(dp));
        memset(flag,true,sizeof(flag));
        int num = 1;
        string boss;
        cin >> boss;
        s[boss] = num++;
        for(int i = 0; i < maxn; i++)
        {
            vi[i].clear();
            dp[i][1] = 1;
            dp[i][0] = 0;

        }
        for (int i = 1; i < n; ++i)
        {
            string a, b;
            cin >> a >> b;
            int aa = s[a];
            int bb = s[b];
            if(aa == 0)
            {
                aa = num++;
                s[a] = aa;
            }
            if(bb == 0)
            {
                bb = num++;
                s[b] = bb;
            }
            vi[bb].push_back(aa);
        }
        dfs(1);
        printf("%d ",max(dp[1][0],dp[1][1]) );
        if (dp[1][0]>dp[1][1]&&flag[1][0]
        	||dp[1][1]>dp[1][0]&&flag[1][1])
        {
        	cout<<"Yes"<<endl;
        }
        else
        	cout<<"No"<<endl;
    }
    return 0;
}
posted @ 2018-08-06 10:41  cifiyoo  阅读(196)  评论(0编辑  收藏  举报