POJ3342 Party at Hali-Bula(树形DP)

本文介绍了一种使用树形动态规划(DP)的方法来解决一个特定问题:如何确定最多可以邀请多少员工参加聚会,同时确保没有直接上下属关系的员工同时出席。通过链式前向星的数据结构实现高效的搜索过程。

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

题目大意:

有n个人要一起聚会,规定直接上司不能和他的直接下属一起出席。问最多能去几人是唯一解吗?

题目思路:树形DP+链试前向星:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
int to1[210],begin1[210],next1[210],d[210][2],u[210][2],e;
char s[210][210],a[210],b[210];

using namespace std;
void add(int x,int y){//链试前向星
    to1[e]=y;
    next1[e]=begin1[x];
    begin1[x]=e++;
}
void dfs(int x){//搜索
    int i;
    d[x][0]=0;
    d[x][1]=1;
    u[x][0]=1;
    u[x][1]=1;
    for(i=begin1[x];i!=-1;i=next1[i]){
        int t=to1[i];
        dfs(t);
        d[x][0]+=max(d[t][0],d[t][1]);//当不取时选下级选与不选的最小值
        d[x][1]+=d[t][0];//当选时下级不能选
        if(d[t][0]>d[t][1] &&d[t][0]==0)u[x][0]=0;//判断是不是唯一解
        else if(d[t][1]>d[t][0] && d[t][1]==0)u[x][0]=0;
        else if(d[t][0]==d[t][1])u[x][0]=0;
        if(u[t][0]==0)u[x][1]=0;
    }
}
int main(void){
    int i,j,k,m,n,sum,sum1;
    while(scanf("%d",&n)!=EOF&&n){
        scanf("%s",s[1]);
        memset(begin1,-1,sizeof(begin1));//清空
        e=0;
        k=1;
        for(i=1;i<n;i++){
            scanf("%s%s",a,b);//输入
            sum=sum1=-1;
            for(j=1;j<=k;j++){
                if(strcmp(a,s[j])==0)sum=j;
                if(strcmp(b,s[j])==0)sum1=j;
            }
            if(sum==-1){//存入s
                k++;
                sum=k;
                strcpy(s[k],a);
            }
            if(sum1==-1){
                k++;
                sum1=k;
                strcpy(s[k],b);
            }
            add(sum1,sum);//将它计入链试前向星
        }
        memset(d,0,sizeof(d));
        dfs(1);
        if(d[1][0]>d[1][1] &&u[1][0]==1)printf("%d Yes\n",d[1][0]);
        else if(d[1][1]>d[1][0] &&u[1][1]==1)printf("%d Yes\n",d[1][1]);
        else printf("%d No\n",max(d[1][1],d[1][0]));

    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值