Poj3342 Party At Hali-Bula 树型dp

题目传送门

http://poj.org/problem?id=3342

因为名字是唯一的,所以可以采用map来对名字进行编号,再通过vector建立树的关系。

AC代码

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <memory.h>
#include <vector>
#include <map>
//dp[u][0],f[u][0]表示在以u为根的树中,不选u结点时能达到的最大人数以及是否唯一
//dp[u][1],f[u][1]表示在以u为根的树中,选u结点时能达到的最大人数以及是否唯一
//所以可得到状态转移方程dp[u][0]+=max(dp[t][0]+dp[t][1])
//dp[u][1]+=dp[t][0]
//且在初始状态dp[u][0]因为不选自己所以肯定为0,dp[u][1]因为选了自己所以为1
//若f[t][0]==f[t][1],则f[u][0]肯定不唯一
//为什么是f[u][0]呢?因为如果能在儿子结点取与不与之间判断,则说明父结点肯定没有被取
//若f[t][0]==0即子结点不唯一,则父节点肯定不唯一,所以f[u][1]=0
//因为不选儿子结点时,得到状态不唯一,则选父亲结点时,状态也肯定不唯一
//然后来讨论dp[u][0]时唯一性的问题,因为dp[u][0]+=max(dp[t][0]+dp[t][1])
//所以比较dp[t][1]与dp[t][0]的大小,若较大的那个状态不唯一,则dp[u][0]状态肯定不唯一
using namespace std;
const int maxn=1000;
int n,len;
int dp[maxn][2],f[maxn][2];
vector<int> v[maxn];
map<string,int> m;
string s,s1,s2;
void dfs(int u){
    dp[u][0]=0;dp[u][1]=1;
    f[u][0]=f[u][1]=1;
    for(int i=0;i<v[u].size();i++){
        int t=v[u][i];
        dfs(t);
        dp[u][0]+=max(dp[t][0],dp[t][1]);
        dp[u][1]+=dp[t][0];
        if(dp[t][0]>dp[t][1]&&f[t][0]==0)f[u][0]=0;
        else if(dp[t][1]>dp[t][0]&&f[t][1]==0)f[u][0]=0;
        else if(dp[t][1]==dp[t][0])f[u][0]=0;
        if(f[t][0]==0)f[u][1]=0;
    }
}
int main() {
    while(scanf("%d",&n)&&n){
        for(int i=0;i<=n;i++)v[i].clear();
        memset(dp,0, sizeof(dp));
        memset(f,0, sizeof(f));
        m.clear();
        len=1;
        cin>>s;
        m[s]=len++;
        for(int i=1;i<=n-1;i++){
            cin>>s1>>s2;
            if(m.count(s1)==0)m[s1]=len++;
            if(m.count(s2)==0)m[s2]=len++;
            v[m[s2]].push_back(m[s1]);
        }
        dfs(1);
        if(dp[1][0]>dp[1][1]&&f[1][0])printf("%d Yes\n",dp[1][0]);
        else if(dp[1][1]>dp[1][0]&&f[1][1])printf("%d Yes\n",dp[1][1]);
        else printf("%d No\n",max(dp[1][0],dp[1][1]));
    }
}
发布了18 篇原创文章 · 获赞 15 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Juicewyh/article/details/83749229