uva 1220 - Party at Hali-Bula

//uva  1220 - Party at Hali-Bula

/*
 赤裸裸的树的最大独立集
 对于以i为根的子树,其最大独立集为 d[i].
 则有 d[i] = max(sum(d[j]),sum(d[k]) +1 ) . 其中d[j]表示 d[i]的儿子节点最大独立集.d[k]表示d[i]的孙子节点的最大独立集。
 在这里我们可以使用递归的方法来求得这个d数组。使用flag标记当取得最优值的时是那种情况。
 
 */


#include <iostream>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
#define ll long long
using namespace std ;
const int maxn = 210 ;
vector<int> son[maxn] ;
int flag[maxn];
int d[maxn] ;
int dp(int u )
{
    if (d[u]!=-1) {
        return d[u] ;
    }
    if (!son[u].size()) {
        flag[u]=0 ;
       return  d[u] = 1 ;
    }
    else{
        int len  = (int)son[u].size() ;
        int ans1 =0,ans2 = 0 ;
        for (int i = 0; i < len; i++) {
            int v = son[u][i] ;
            ans1 += dp(v) ;
            int len1 = (int)son[v].size() ;
            for (int j = 0 ; j < len1; j++) {
                ans2+= dp(son[v][j]) ;
            }
        }
        ans2+=1 ;
        if (ans2 == ans1) {
            flag[u] = 1 ;
            return  d[u] = ans1  ;
        }
        else{
            if (ans1 > ans2) {
                flag[u] = 2 ;
                d[u] = ans1 ;
            }
            else{
               flag[u] = 3 ;
                d[u] = ans2 ;
            }
            return d[u] ;
        }
    }
}
bool isOnlyOne(int u)
{
    if (flag[u]==1 ) {
        return true ;
    }
    else if(flag[u]==2){
        int len = (int)son[u].size() ;
        for (int i = 0; i < len; i++) {
            if (isOnlyOne(son[u][i])) {
                return true ;
            }
        }
    }
    else if(flag[u] == 3  ){
        int len = (int)son[u].size() ;
        for (int i = 0; i < len; i++) {
            int v = son[u][i] ;
            int len2 = (int)son[v].size()  ;
            for (int j = 0 ; j < len2; j++) {
                if (isOnlyOne(son[v][j])) {
                    return true ;
                }
            }
        }
    }
    else{
        return false ;
    }
    return false ;
}
map<string , int > name ;
int main() {
    int n  ;
    string str,str1 ;
    int  t = 0 ;
    while (scanf("%d" , &n),n) {
        t = 0 ;
        cin>>str ;
        name.clear() ;
        name[str] = 0 ;t++ ;
        for (int i = 0; i <n+1; i++) {
            son[i].clear()  ;
        }
        int b ,sub ;
        for (int i = 0; i < n -1; i++) {
            cin >>str>>str1 ;
            if (name.count(str)) {
                b =  name[str] ;
            }
            else
            {
                b = t++ ;name[str] = b  ;
            }
            if (name.count(str1)) {
                sub =  name[str1] ;
            }else
            {
                sub = t++ ;name[str1] = sub  ;
            }
            son[sub].push_back(b)   ;
        }
        memset(flag, 0, sizeof(flag)) ;
        memset(d, -1, sizeof(d)) ;
        cout<<dp(0) ;
        if (isOnlyOne(0)) {
            cout<<' '<<"No" ;
        }
        else{
            cout << ' ' <<"Yes";
        }
        cout << endl ;
    }
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值