POJ 2342 Anniversary party(树形dp - 入门)

链接:http://poj.org/problem?id=2342
来源:POJ

  • Description
    There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The University has a hierarchical structure of employees. It means that the supervisor relation forms a tree rooted at the rector V. E. Tretyakov. In order to make the party funny for every one, the rector does not want both an employee and his or her immediate supervisor to be present. The personnel office has evaluated conviviality of each employee, so everyone has some number (rating) attached to him or her. Your task is to make a list of guests with the maximal possible sum of guests’ conviviality ratings.
  • Input
    Employees are numbered from 1 to N. A first line of input contains a number N. 1 <= N <= 6 000. Each of the subsequent N lines contains the conviviality rating of the corresponding employee. Conviviality rating is an integer number in a range from -128 to 127. After that go N – 1 lines that describe a supervisor relation tree. Each line of the tree specification has the form:
    L K
    It means that the K-th employee is an immediate supervisor of the L-th employee. Input is ended with the line
    0 0
  • Output
    Output should contain the maximal sum of guests’ ratings.
  • Sample Input
    7
    1
    1
    1
    1
    1
    1
    1
    1 3
    2 3
    6 4
    7 4
    4 5
    3 5
    0 0
  • Sample Output
    5
  • 树形dp(树上最优解问题)
    在“树”上进行的dp:给出一棵树,要求以最少的代价(或者取得最大收益)完成给定的操作。通常这类问题规模较大,枚举算法的效率低,无法胜任,贪心算法无法得到最优解,因此需要用到动态规划。

  题意:一颗有根树上每个结点有一个权值,相邻的父结点和子结点只能选择一个,问如何选择这些结点可以使得这棵树的总权值最大。
  思路: 对于
            5
            1
            1
            1
            1
            1
            1 3
            2 3
            4 5
            3 5
            0 0
  这棵树:
            在这里插入图片描述
  我们知道,动态规划一般都是自下而上的,我们用 d p [ i ] [ j ] dp[i][j] dp[i][j] 来表示结点 i i i j j j 状态下的最大权值。 j = 0 j = 0 j=0 表示不选择这个结点,反之选择这个结点。从叶子结点开始,他们有两种状态,选择和不选择,可以得到一个dp值,向上回溯的时候我们到达父亲结点 3 3 3,如果这个结点选择表示他的子结点不选择,那么就有 d p [ u ] [ 1 ] dp[u][1] dp[u][1] + + + = = = d p [ v ] [ 0 ] dp[v][0] dp[v][0],如果我们不选择这个结点,表示他的子结点可选可不选,此时就有 d p [ u ] [ 0 ] dp[u][0] dp[u][0] + + + = = = m a x ( d p [ v ] [ 0 ] , d p [ v ] [ 1 ] ) max(dp[v][0],dp[v][1]) max(dp[v][0],dp[v][1])。此时之所以不考虑 u u u 的父亲是因为我们最后只关注根结点的最终状态,它包含了前面的所有状态,所以每次只需要考虑当前结点和其子结点的状态即可。用 d f s dfs dfs 递归到叶子结点,然后不断的回溯更新每一个结点的最大权值,最后根结点的状态就代表了整棵树的状态。

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<vector>
using namespace std;

typedef long long ll;
const int Max_n=1e6+10;
int val[Max_n],father[Max_n],dp[Max_n][2];

vector<int>tree[Max_n];

void dfs(int u){
    dp[u][0]=0;dp[u][1]=val[u];
    for(int i=0;i<(int)tree[u].size();i++){
        int v=tree[u][i];
        dfs(v);
        dp[u][0]+=max(dp[v][1],dp[v][0]);
        dp[u][1]+=dp[v][0];
    }
}

int main(){
    int n; scanf("%d",&n);
    for(int i=1;i<=n;i++) father[i]=-1;
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    int a,b;
    while(scanf("%d%d",&a,&b)&&a&&b){
        tree[b].push_back(a);
        father[a]=b;
    }
    int node=1;
    while(father[node]!=-1) node=father[node];
    dfs(node);
    printf("%d\n",max(dp[node][0],dp[node][1]));
    return 0;
}


/**
* Copyright(c)
* All rights reserved.
* Author : Max_n
* Date : 2019-10-04-15.59.52
* Description : 树的直径预备知识
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值