现在的位置: 首页 > 综合 > 正文

poj2342 Anniversary party

2019年09月22日 ⁄ 综合 ⁄ 共 1170字 ⁄ 字号 评论关闭
/*
 * poj2342 AC
 * 典型的树状DP。
 * dp[i][0]表示员工i参加舞会的最大值,dp[i][1]表示员工i不参加舞会的最大值。
 *
 * dp[i][0] = max(dfs(son[i],1));
 * i参加则i的儿子结点一定不能参加。
 * dp[i][1] = max(dfs(son[i],0),dfs(son[i],1));
 * i不参加则i的儿子结点可参加,也可以不参加。
 *
 * 最初居然考虑错误,实在不应该,此题和摘苹果那题还是有区别的,每个结点要记录两个
 * 状态,而非一个。
 * */
#include<cstdio>
#include<algorithm>
#include<memory.h>
#define MIN (-(1<<30))
using namespace std;

int tree[6005],conv[6005],head[6005],next[6005],num[6005],root;
long dp[6005][2];
long dfs(int x,int state)
{
    if(dp[x][state]!=MIN) return dp[x][state];

    long i;
    if(num[x]==0)
    {
        dp[x][0] = conv[x],dp[x][1] = 0;
        return dp[x][state];
    }

    if(state)
    {
        for(dp[x][state]=0,i=head[x];i;i=next[i])
            dp[x][state] += max(dfs(tree[i],0),dfs(tree[i],1));
    }else
    {
        for(dp[x][state]=conv[x],i=head[x];i;i=next[i])
            dp[x][state] += dfs(tree[i],1);
    }
    return dp[x][state];
}

int main()
{
    int n,i,j,k,tot;
//    FILE* fin;
//    fin = fopen("d.in","r");
//    fscanf(fin,"%d",&n);
    scanf("%d",&n);

    for(i=1;i<=n;i++)
    {
        dp[i][0] = dp[i][1] = MIN;
        scanf("%d",&conv[i]);
//        fscanf(fin,"%d",&conv[i]);
    }
    memset(num,0,sizeof(num));
    for(root=(1+n)*n/2,tot=0,i=1;i<=n-1;i++)
    {
        scanf("%d%d",&j,&k);
//        fscanf(fin,"%d%d",&j,&k);
        tree[++tot] = j,next[tot] = head[k],head[k] = tot,num[k]++,root -= j;
    }
    long ans;
    ans = max(dfs(root,0),dfs(root,1));
    printf("%ld\n",ans);
    return 0;
}

【上篇】
【下篇】

抱歉!评论已关闭.