没有上司的舞会(树形dp)

4867: 没有上司的舞会

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 8  Solved: 8
[Submit][Status][Web Board]

Description

有个公司要举行一场晚会。 
为了能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会邀请他的上司 
(上司的上司,上司的上司的上司……都可以邀请)。 
题目 
每个参加晚会的人都能为晚会增添一些气氛,求一个邀请方案,使气氛值的和最大。 

Input

第1行一个整数N(1<=N<=6000)表示公司的人数。 
接下来N行每行一个整数。第i行的数表示第i个人的气氛值x(-128<=x<=127)。 
接下来每行两个整数L,K。表示第K个人是第L个人的上司。 
输入以0 0结束。 

Output

一个数,最大的气氛值和。 

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
设dp[i][0]表示节点i不参加舞会所以其子节点既可以参加舞会又可以不参加所以
dp[i][0]+=max(dp[son][1],dp[son][0])
同理,dp[i][1]+=dp[son][0]

#include
#include
#include
using namespace std;

const int maxn=6000+10;

int dp[maxn][3];

struct my{
       int v;
       int next;
};

my bian[maxn*2];
int adj[maxn];
bool vis[maxn];
int w[maxn],n,fa;

void myinsert(int u,int v){
     bian[++fa].v=v;
     bian[fa].next=adj[u];
     adj[u]=fa;
}

void dfs(int x){
     vis[x]=true;
     dp[x][0]=0;
     dp[x][1]=w[x];
     for (int i=adj[x];i;i=bian[i].next){
        int v=bian[i].v;
        if(!vis[v]){
            dfs(v);
            dp[x][0]+=max(dp[v][1],dp[v][0]);
            dp[x][1]+=dp[v][0];
        }
     }
}

int main(){
    int u,v;
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&w[i]);
        while(scanf("%d%d",&u,&v)&&u){
        myinsert(u,v);
        myinsert(v,u);
        vis[u]=1;
     }
    int root=0;
    for (int i=1;i<=n;i++) if(!vis[i]) {
            root=i;
            break;
    }
    memset(vis,0,sizeof(vis));
    dfs(root);
    printf("%d\n",max(dp[root][1],dp[root][0]));
return 0;
}

 

 

转载于:https://www.cnblogs.com/lmjer/p/9412092.html

你可能感兴趣的:(没有上司的舞会(树形dp))