hdu 1520 Anniversary party

题意

某人要开一个聚会,每个人都有一个自己的交际评分,但是他们都不想和自己的直接上司在一起,那样会不开心,所以只让一部分人来,希望你能找出评分最大的方案。

解析:

关于上司下级的事情,就会涉及一点并查集,不过这题和并查集没有太大关系,需要建树来维系他们之间的关系,然后用树状dp来写,状态转移方程式为dp[i][0]+=max(dp[j][1],dp[i][0]),dp[i][1]+=dp[j][0];i表示父节点,j为子节点,0的意思是i或j没有出席m,1表示i或j出席了,也就是如果父节点没有出席,子节点可以出席也可以不出席,如果父节点出席了,子节点一定不能出席。

代码:

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define N 6005
#define oo 0x3f3f3f3f
vector<int>G[N];
int n,dp[N][2],father[N];
void dfs(int root)
{
    for(int i=0;i<G[root].size();i++)
    {
        dfs(G[root][i]);
    } 
    for(int i=0;i<G[root].size();i++)
    {
        dp[root][0]+=max(dp[G[root][i]][0],dp[G[root][i]][1]);
        dp[root][1]+=dp[G[root][i]][0];
    }
}
int main()
{
    int u,v;
    while(~scanf("%d",&n))
    {
        memset(father,-1,sizeof(father));
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&dp[i][1]);
            G[i].clear();
        }
        while(scanf("%d%d",&u,&v)&&(u+v))
        {
            father[u]=v;
            G[v].push_back(u);
        }
        int root=1;
        while(father[root]!=-1)
        root=father[root];
        dfs(root);
        printf("%d\n",max(dp[root][1],dp[root][0]));
    }
}

 

posted @ 2018-05-11 11:26  山水有相逢  阅读(114)  评论(0编辑  收藏  举报