zoukankan      html  css  js  c++  java
  • HDOJ2412 Party at HaliBula (树形DP)

    此题是经典树形DP题,没有上司的晚会。

    公司所有人员之间的关系可以用一个树来表示,任何一个人(除了最大的boss外)都有且只有一个直接上司,现要开一个Party,邀请尽量多的人参加,要求任何人不得与直接上司同时参加。

    抽象后的数学模型:在一棵树中,最多能选取多少结点,使得任何结点之间没有直接连边。

    状态设计:d[i][0]表示在以i为根结点的子树中,在不选结点i的情况下最多能选取的结点数目,d[i][1]表示在以i为根结点的子树中,在选取结点i的情况下最多能选取的结点数目。

    状态转移:d[i][0]=(max(d[j][0],d[j][1])),j为i的儿子结点,d[i][1]=∑(d[j][0]),j为i的儿子结点。

    边界条件:当i没有儿子结点时,也即i为叶子结点,此时d[i][0]=0,d[i][1]=1。

    需要注意的是判断最后的解是否唯一,此时可以用一个unique数组来同步记录,unique[i][0]记录以i为根结点且不选i时取最多的点是否唯一,unique[i][1]记录以i为根结点且选i时取最多结点是否唯一。在状态转移时同步更新unique数组。

    View Code
    #include <stdio.h>
    #include <string.h>
    #include <vector>
    using namespace std;
    #define MAX(a,b) ((a)>(b)?(a):(b))
    #define N 200
    #define LEN 101
    char name[N][LEN];
    char s[LEN];
    int n,top;
    int p[N],d[N][2];
    char unique[N][2];
    vector<int> son[N];
    int find()
    {
        for(int i=0;i<top;i++)    if(strcmp(name[i],s)==0)    return i;
        strcpy(name[top++],s);
        return top-1;
    }
    int dp(int i,int f)
    {
        int j,k,ans,cnt=son[i].size();
        if(d[i][f]!=-1) return d[i][f];
        if(f)
        {
            ans=1;
            for(k=0;k<cnt;k++)
            {
                j=son[i][k];
                ans+=dp(j,0),unique[i][f]&=unique[j][0];
            }
        }
        else
        {
            ans=0;
            for(k=0;k<cnt;k++)
            {
                j=son[i][k];
                ans+=MAX(dp(j,0),dp(j,1));
                if(dp(j,0)==dp(j,1))    unique[i][f]=false;
                if(dp(j,0)>dp(j,1)) unique[i][f]&=unique[j][0];
                else unique[i][f]&=unique[j][1];
            }
        }
        return d[i][f]=ans;
    }
    void clear()
    {
        for(int i=0;i<n;i++)    son[i].clear();
    }
    int main()
    {
        int i,a,b;
        bool flag;
        while(scanf("%d",&n)&&n)
        {
            clear();
            top=0;
            scanf("%s",s);
            p[find()]=-1;
            for(i=1;i<n;i++)
            {
                scanf("%s",s);
                a=find();
                scanf("%s",s);
                b=find();
                p[a]=b;
                son[b].push_back(a);
            }
            memset(d,-1,sizeof(d[0])*n);
            memset(unique,1,sizeof(unique[0])*n);
            a=dp(0,0);
            b=dp(0,1);
            if(a==b)    flag=false;
            else if(a>b)    flag=unique[0][0];
            else    flag=unique[0][1];
            printf("%d %s\n",MAX(a,b),flag?"Yes":"No");
        }
        return 0;
    }
  • 相关阅读:
    redis 基本操作-python 使用redis-手机验证接口-发送短信接口
    登录-注册页面修订
    10-29 课堂笔记
    git 协作开发
    git 常规使用
    luffy-city 基础环境搭建(至轮播图前后台交互实现)-步骤目录
    偏移分页-游标(加密)分页-自定义过滤器-第三方过滤器插件(django-filter)
    drf 大总结
    739. Daily Temperatures
    617. Merge Two Binary Trees
  • 原文地址:https://www.cnblogs.com/algorithms/p/2601447.html
Copyright © 2011-2022 走看看