• 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 1042 N!
    hdu 1002 A + B Problem II
    c++大数模板
    hdu 1004 Let the Balloon Rise
    hdu 4027 Can you answer these queries?
    poj 2823 Sliding Window
    hdu 3074 Multiply game
    hdu 1394 Minimum Inversion Number
    hdu 5199 Gunner
    九度oj 1521 二叉树的镜像
  • 原文地址:https://www.cnblogs.com/lienus/p/4209680.html
Copyright © 2020-2023  润新知