HDOJ 1520 Anniversary party

树状DP入门。每组数据只有一颗树。一开始当二叉做,错了- -!一开始子节点开了1005,后来又试了105,都可以。

重写一遍,邻接表~当初的写法不忍直视。。。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 100005
typedef long long LL;
struct Tree{
    int val;
    Tree * next;
}e[N], * head[N];
int par[N];
int v[N];
int n;
int ptr;
void init(){
    ptr = 0;
    for(int i = 1; i <= n; i++){
        par[i] = i;
    }
    memset(head, NULL, sizeof(head));
}
void Insert(int x, int y){
    par[x] = y;
    e[ptr].val = x;
    e[ptr].next = head[y];
    head[y] = &e[ptr++];
}
int tdp(int x){
    Tree *p;
    int ans0 = 0;
    int ans1 = v[x];
    p = head[x];
    while(p != NULL){
        ans0 += tdp(p -> val);
        Tree *pp = head[p -> val];
        while(pp != NULL){
            ans1 += tdp(pp -> val);
            pp = pp -> next;
        }
        p = p -> next;
    }
    return max(ans0, ans1);
}
int main(){
    while(scanf("%d", &n) != EOF){
        init();
        for(int i = 1; i <= n; i++){
            scanf("%d", &v[i]);
        }
        int x, y;
        while(scanf("%d%d", &x, &y), x || y){
            Insert(x, y);
        }
        int root = 0;
        for(int i = 1; i <= n; i++){
            if(par[i] == i)root = i;
        }
        printf("%d\n", tdp(root));
    }
    return 0;
}


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
struct Node
{
    int par;
    int v;
    int son[105];//HDOJ数据中子节点105即可
    int num;
}a[6005];
int r[6005];
int v[6005];
void init (int n)
{
    for(int i=0;i<=n;i++)
    {
        a[i].par=i;
        a[i].v=0;
        a[i].num=0;
    }
}
int dfs(int x)
{
    if(v[x]!=0)return r[x];
    if(x==0)return 0;
    v[x]=1;
    if(a[x].num==0){r[x]=a[x].v;return r[x];}

    int i0=0,i1=a[x].v;
    for(int i=0;i<a[x].num;i++)
    {
        i0+=dfs(a[x].son[i]);
        for(int j=0;j<a[a[x].son[i]].num;j++)
        {
            i1+=dfs(a[a[x].son[i]].son[j]);
        }
    }
    r[x]=max(i0,i1);
    return r[x];
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(v,0,sizeof(v));
        init (n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i].v);
        }
        int x,y,k=0;
        while(scanf("%d%d",&x,&y),x||y)
        {
            a[x].par=y;
            a[y].son[a[y].num]=x;
            a[y].num++;
        }
        x=1;
        while(a[x].par!=x)
        {
            x=a[x].par;
        }
        int ans=dfs(x);
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值