poj 3342

简单树形DP,父节点要么去要么不去;

res[i]=max(∑res[child[i]],∑res[child(child[i])]);

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct node
{
    int i,next;
}vert[201];
char name[201][20];
int head[201],res[201],go[201],nogo[201],N,count;
int find(char * str)
{
    int i;
    for(i=1;i<N;i++)
        if(strcmp(name[i],str)==0) return i;
    strcpy(name[N],str);
    return N++;
}
int add(int s,int t)
{
    vert[count].i=t;
    vert[count].next=head[s];
    return count++;
}
int GetRes(int root)
{
    int j,k,sum1=0,sum2=0;
    if(head[root]==0) 
    {
        res[root]=1;
        go[root]=1;  nogo[root]=0;
        return res[root];
    }
    for(j=head[root];j;j=vert[j].next)
    {
        sum1+=GetRes(vert[j].i);
        for(k=head[vert[j].i];k;k=vert[k].next)
            sum2+=res[vert[k].i];
    }

    go[root]=sum1;  
    nogo[root]=sum2+1;
    res[root]=go[root] > nogo[root] ? go[root] : nogo[root];

    return res[root];
}
int judge(int root)
{
    int j,k;
    if(head[root]==0) return 1;
    if(go[root]==nogo[root]) return 0;
    if(go[root]>nogo[root])
    {
        for(j=head[root];j;j=vert[j].next)
            if(!judge(vert[j].i)) return 0;
    }
    else
    {
        for(j=head[root];j;j=vert[j].next)
            for(k=head[vert[j].i];k;k=vert[k].next)
                if(!judge(vert[k].i)) return 0;
    }
    return 1;
}
int main()
{
    int i,k,n,s,t;
    char str1[20],str2[20];
    while(scanf("%d",&n) && n)
    {
        N=count=1;
        memset(head,0,sizeof(head));
        scanf("%s",str1);
        k=find(str1);
        for(i=1;i<n;i++) 
        {
            scanf("%s %s",str1,str2);
            s=find(str1);
            t=find(str2);
            head[t]=add(t,s);
        }
                printf("%d ",GetRes(k));
        if(judge(k)) printf("Yes\n");
        else printf("No\n");

    }
    return 0;
}

转载于:https://www.cnblogs.com/yu-chao/archive/2012/06/09/2542904.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值