POJ 2342 Anniversary party / HDU 1520 Anniversary party / URAL 1039 Anniversary party(树型动态规划)

POJ 2342 Anniversary party / HDU 1520 Anniversary party / URAL 1039 Anniversary party(树型动态规划)

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

Http

POJ:https://vjudge.net/problem/POJ-2342
HDU:https://vjudge.net/problem/HDU-1520
URAL:https://vjudge.net/problem/URAL-1039

Source

树型动态规划

题目大意

在一棵树上选取若干个点使得这些点均不互相相邻,且点权值之和最大。

解决思路

令F[i]表示以i为根节点的一棵子树的最大权值,F[i][0]表示不取i点的最大权值,F[i][1]表示取i点的最大权值。对于i的所有儿子节点j,则有F[i][0]=sum(max(F[j][1],F[j][0])) ,F[i][1]=sum(F[j][0])+Value[i];

有了状态转移方程,我们就可以用dfs的方式依次求解了。

需要注意的是,每个OJ的题面都没有表示有多组数据,POJ确实只有一组数据,而HDU是有多组数据的,在写的时候要注意。

这道题的加强版在这里(需要判断最优解是否唯一)

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

const int maxN=7000;
const int inf=2147483647;

int n;
int F[maxN][3];
int Happy[maxN];//每个点中的权值
vector<int> E[maxN];//存原图,里面的边是雇员->上司
vector<int> E2[maxN];//存返图,里面的边是上司->雇员

void dfs(int u);

int main()
{
    while (cin>>n)
    {
        if (n==0)
            break;
        memset(F,0,sizeof(F));
        for (int i=0;i<=n;i++)//因为有多组数据,所以每一次都要清空
        {
            E[i].clear();
            E2[i].clear();
        }
        for (int i=1;i<=n;i++)
            cin>>Happy[i];
        int u,v;
        while (cin>>u>>v)
        {
            if ((u==0)&&(v==0))
                break;
            E[u].push_back(v);
            E2[v].push_back(u);
        }
        int start;
        for (int i=1;i<=n;i++)
            if (E[i].size()==0)
            {
                start=i;
                break;
            }
        dfs(start);
        cout<<max(F[start][1],F[start][0])<<endl;
    }
    return 0;
}

void dfs(int u)//dfs求F
{
    for (int i=0;i<E2[u].size();i++)
    {
        int v=E2[u][i];
        dfs(v);
        F[u][0]=F[u][0]+max(F[v][0],F[v][1]);
        F[u][1]=F[u][1]+F[v][0];
    }
    F[u][1]=F[u][1]+Happy[u];
    return;
}
posted @ 2017-07-08 21:55  SYCstudio  阅读(247)  评论(0编辑  收藏  举报