zoukankan      html  css  js  c++  java
  • hdu2412(树形dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2412

    题意:给定一棵关系树 , 从中选择一些点 , 使这些点均不存在亲子关系 , 最多能取多少个点 , 并且判断取法是否唯一 .

    分析:如果这题没有判断唯一性,就和hdu1520一样了。 dp[i][0] 为在以 i 为根的子树中 , 不选择点 i 最多能够选的数目 ,dp[i][1] 为选择 i 点的最多数目 .

    状态转移方程 :

    当 u 为叶子节点时 :

    dp[u][0]=0;

    dp[u][1]=1;

    当 u 为非叶子节点时 :

    dp[u][0]=sum(max(dp[v][0],dp[v][1]))  (v 为 u 的儿子 )

    dp[u][1]=sum(dp[v][0])  (v 为u 的儿子 )

    至于判断唯一性:初始化flag数组全为1,即可行的唯一的。如果父节点以下的某一节点取时不唯一了,递归上去的结果也必定不唯一。

    if(dp[v][0]>dp[v][1]&&flag[v][0]==0)flag[u][0]=0;//如果取子节点v即dp[v][0]时而flag[v][0]=0;由于dp[u][0]会取dp[v][0]使得flag[u][0]也变为0,即不唯一了

    else if(dp[v][1]>dp[v][0]&&flag[v][1]==0)flag[u][0]=0;;//同理取dp[v][1]时而flag[v][1]=0;由于dp[u][0]会取dp[v][1]使得flag[u][0]也变为0,即不唯一了

    else if(dp[v][0]==dp[v][1])flag[u][0]=0;//不唯一的源头

    if(flag[v][0]==0)flag[u][1]=0;//由于dp[u][1]必取dp[v][0],所以flag[v][0]为0的话,flag[u][1]也不唯一了。

    #pragma comment(linker,"/STACK:102400000,102400000")
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <cstdlib>
    #include <stack>
    #include <vector>
    #include <set>
    #include <map>
    #define LL long long
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define N 210
    #define FILL(a,b) (memset(a,b,sizeof(a)))
    using namespace std;
    struct edge
    {
        int next,v;
        edge(){}
        edge(int v,int next):v(v),next(next){}
    }e[N*2];
    int head[N],tot;
    int num,n;
    int dp[N][2],flag[N][2];
    void addedge(int u,int v)
    {
        e[tot]=edge(v,head[u]);
        head[u]=tot++;
    }
    void dfs(int u,int fa)
    {
        dp[u][0]=0;dp[u][1]=1;
        flag[u][0]=flag[u][1]=1;
        for(int i=head[u];~i;i=e[i].next)
        {
            int v=e[i].v;
            if(v==fa)continue;
            dfs(v,u);
            dp[u][1]+=dp[v][0];
            dp[u][0]+=max(dp[v][0],dp[v][1]);
            if(dp[v][0]>dp[v][1]&&flag[v][0]==0)flag[u][0]=0;
            else if(dp[v][1]>dp[v][0]&&flag[v][1]==0)flag[u][0]=0;
            else if(dp[v][0]==dp[v][1])flag[u][0]=0;
            if(flag[v][0]==0)flag[u][1]=0;
        }
    }
    
    char str[N],s1[N],s2[N];
    int main()
    {
        while(scanf("%d",&n)&&n)
        {
            tot=0;num=0;
            map<string,int>mp;
            FILL(head,-1);
            scanf("%s",str);
            mp[str]=++num;
            for(int i=1;i<n;i++)
            {
                scanf("%s%s",s1,s2);
                if(mp.find(s1)==mp.end())mp[s1]=++num;
                if(mp.find(s2)==mp.end())mp[s2]=++num;
                addedge(mp[s1],mp[s2]);
                addedge(mp[s2],mp[s1]);
            }
            dfs(1,-1);
            if(dp[1][1]>dp[1][0]&&flag[1][1]==1)
                printf("%d Yes
    ",dp[1][1]);
            else if(dp[1][0]>dp[1][1]&&flag[1][0]==1)
                printf("%d Yes
    ",dp[1][0]);
            else printf("%d No
    ",max(dp[1][0],dp[1][1]));
        }
    }
    View Code
  • 相关阅读:
    hdu 2203
    hdu 3081
    hdu 4240 最大流量路径
    b_vj_Fiber Network(floyd思想+状态压缩)
    b_vj_Corn Fields(预处理行的状态、合法状态+枚举当前行与上一行的状态)
    b_vj_Hackers' Crackdown(预处理所有集合+检查合法集合后进行状态转移)
    b_vj_Count Color(线段树+二进制表示颜色)
    b_vj_K-th Number(二分+线段树)
    b_lg_火烧赤壁(讨论完全覆盖/部分覆盖)
    b_hdu_Ping pong(树状数组+乘法原理)
  • 原文地址:https://www.cnblogs.com/lienus/p/4209680.html
Copyright © 2011-2022 走看看