题意:宴会举办者要邀请一批客人,所有客人之间的关系可以看成一棵树,上层的监督下层的。已知直接相邻层的人不能被同时邀请,而且每个人有个欢乐值。问举办者如何邀请客人能满足上述条件,而且使得欢乐值最大。
思路:树形dp(树上的带权最大独立集问题)。从root开始搜索,dp[i][0]表示在以i为root的子树中不邀请i客人达到的最大欢乐值,dp[i][1]表示在以i为root的子树中邀请i客人达到的最大欢乐值。邀请了i,那么i的所有直接下层节点必然不能邀请,未邀请i,其直接下层节点可请可不请。
#include <stdio.h>
#include <string.h>
#define N 6005
#define max(a,b) ((a)>(b)?(a):(b))
struct edge{
int y,next;
}e[N];
int dp[N][2],s[N],first[N],flag[N];
int n,top;
void add(int x,int y){
e[top].y = y;
e[top].next = first[x];
first[x] = top++;
}
void dfs(int x){
int i,y;
dp[x][1] = s[x];
for(i = first[x];i!=-1;i=e[i].next){
y = e[i].y;
dfs(y);
dp[x][1]+=dp[y][0];
dp[x][0]+=max(dp[y][0],dp[y][1]);
}
}
int main(){
freopen("a.txt","r",stdin);
while(scanf("%d",&n)!=EOF){
int i,a,b;
memset(dp,0,sizeof(dp));
memset(first,-1,sizeof(first));
memset(flag,0,sizeof(flag));
top = 0;
for(i = 1;i<=n;i++)
scanf("%d",&s[i]);
for(i = 1;i<