HDU 1520 Anniversary party【树形DP】

来源:互联网 发布:the piano guys知乎 编辑:程序博客网 时间:2024/06/15 23:17

Problem 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 T 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

Source

Ural State University Internal Contest October’2000 Students Session

Recommend

linle | We have carefully selected several similar problems for you: 1561 1011 2196 1494 2242

第一次接触树形DP。
直接了当的说吧,之前是在线性表上DP,比方说是数组链表之类。而树形DP则是在一棵树上进行DP。 不知道是不是能联想起之前那种数塔的那种DP的那种问题。 这个最基本的题相当于是在那种基础之上增加了一些条件,必须要用到递归的知识才能更好的解决。

题意:有一个饭局,每个人都有一定的价值,许多人都是领导和下属的关系,为了避免尴尬,不能让你一个人和他的上司和下属吃饭。当然越级是可以的~,你的上司不是我的上司,你的下属不是我的下属。

这个时候就可以表示dp[i][0],第i个人不去,然后我们通过递归来选择他的直系下属.打破dp[i][1]表示,第i个人去.
dp[node][1] += dp[i][0];
dp[node][0] += max(dp[i][1], dp[i][0]);

第一遍,觉得思路没问题,TLE,再学习。
问题出在调用外函数上,如果调用结构体内部函数就很舒服,向荣耀之路前辈学习了一手。
TLE:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define maxn 6010int n;int dp[maxn][2], father[maxn];//dp[i][0]表示不去,dp[i][1]表示1就位bool vis[maxn];void tree_dp(int node)//树形DP,这个题比较基础说白了就是一个数塔的基本操作+DP;{    int i;    vis[node] = 1;    for (i = 1; i <= n; i++)//觉得递归越来越好玩了= =    {        if (!vis[i] && father[i] == node)//i为node员工        {            tree_dp(i);            dp[node][1] += dp[i][0];            dp[node][0] += max(dp[i][1], dp[i][0]);        }    }}int main(){    int i;    int f, c, root;    while (cin >> n)    {        memset(dp, 0, sizeof(dp));        memset(father, 0, sizeof(father));        memset(vis, 0, sizeof(vis));        for (i = 1; i <= n; i++)        {            cin >> dp[i][1];        }        root = 0;        bool beg = 1;//跟朋友学习的一手操作        while (cin >> c >> f, c || f)        {            father[c] = f;            if (root == c || beg)            {                root = f;            }        }        while (father[root])            root = father[root];        tree_dp(root);        int MAX = max(dp[root][0], dp[root][1]);        cout << MAX << endl;    }    return 0;}

AC: 再学习!

#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;struct node{    int child, father, brother, present, not_present;    int max()//结构体内的函数调用时耗时少    {        return present>not_present ? present : not_present;    }    void init()    {        child = father = brother = not_present = 0;    }}tree[6005];void dfs(int root){    int son = tree[root].child;    while (son)    {        dfs(son);        tree[root].present += tree[son].not_present;        tree[root].not_present += tree[son].max();        son = tree[son].brother;    }}int main(){    int n, i, j, k, l;    while (~scanf("%d", &n) && n)    {        for (i = 1; i <= n; i++)        {            scanf("%d", &tree[i].present);            tree[i].init();        }        while (~scanf("%d%d", &l, &k), l + k)        {            tree[l].father = k;            tree[l].brother = tree[k].child;            tree[k].child = l;        }        for (i = 1; i <= n; i++)        {            if (!tree[i].father)            {                dfs(i);                printf("%d\n", tree[i].max());                break;            }        }    }    return 0;}