poj3342 Party at Hali-Bula

本文深入探讨了DP算法中的一种特定应用案例,通过定义状态dp[i][1]和dp[i][0]来解决树形结构上的最大值问题,并提供了一种判断解是否唯一的有效方法。此外,还详细介绍了算法实现过程及核心代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
用dp[i][1]表示选择结点i时以i为跟结点的子树能得到的最大值,dp[i][0]为不选i时的最大值,
则dp[i][0]+=max(dp[j][0],dp[j][1]),dp[i][1]+=sum{dp[j][0]},其中j为i的儿子;
边界为d[k][1]=1,d[k][0]=0(k为叶子节点)
本题比较难一点的是判断解得唯一性。我的判断方法是:如果dp[i][0]>=dp[i][1],
且dp[j][0]==dp[j][1](j为i的孩子),就可以判定为不唯一了。
对于根结点 如果dp[0][1]==dp[0][0] 可知不唯一;
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define MAXSIZE 1000
#define sf scanf
#define pf printf
#define __int64 long long
#define INF 0xfffffff
using namespace std;
struct node
{
    int v,next;
}edge[MAXSIZE*4];
int head[MAXSIZE],ant,dp[MAXSIZE][2];
char s[250][20];
void add(int u,int v)
{
    edge[ant].v=v;
    edge[ant].next=head[u];
    head[u]=ant++;
}
void DFS(int r,int f)
{
    dp[r][1]=1;
    dp[r][0]=0;
    for(int i=head[r];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==f) continue;
        DFS(v,r);
        dp[r][0]+=max(dp[v][0],dp[v][1]);
        dp[r][1]+=dp[v][0];
    }
}
bool cheak(int n)
{
    for(int i=0;i<n;i++)
    {
        if(dp[i][0]>=dp[i][1])
        {
            for(int j=head[i];j!=-1;j=edge[j].next)
            {
                int v=edge[j].v;
                if(i==v) continue;
                if(dp[v][0]==dp[v][1]) return false;
            }
        }
    }
    return true;
}
int main()
{
    int n,sum;
    while(sf("%d",&n),n)
    {
        ant=0;
        sum=1;
        memset(dp,0,sizeof(dp));
        memset(head,-1,sizeof(head));
        char a[20],b[20];
        scanf("%s",s[0]);
        int u,v;
        for(int i=1;i<n;i++)
        {
            u=v=-1;
            scanf("%s%s",&a,&b);
            for(int i=0;i<sum;i++)
            {
                if(strcmp(a,s[i])==0) {u=i;}
                if(strcmp(b,s[i])==0) {v=i;}
            }
            if(u==-1) {u=sum;strcpy(s[sum++],a);}
            if(v==-1) {v=sum;strcpy(s[sum++],b);}
            //cout<<u<<" "<<v<<endl;
            add(u,v);
            add(v,u);
        }
        DFS(0,-1);

        int worth=max(dp[0][0],dp[0][1]);
        bool flag=cheak(sum);
        if(dp[0][0]==dp[0][1]) flag=false;
        cout<<worth<<" ";
        if(flag) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值