luogu#P1352 没有上司的舞会
题意:
给出一棵树,编号 \(1\) ~ \(N\) 和每个节点上的快乐值 \(R[i]\) 。如果一个节点的父节点被选中,那么这个节点就不能选了。求最大快乐值。
写博客的时候才注意到输入格式有一条 最后一行输入0 0,貌似没有任何用处
解法:
树形dp 记忆化搜索
设 \(f[i][j]\) = 以 \(i\) 为根的子树中, \(i\) 取( \(j=1\) )不取( \(j=0\) )的最大值
因为题目没有给出树根,所以得把树根手动求出来。
然后从根部搜索,扫描所有可以到达的点 \(v\) ,dp(v),则
f[x][1]=max( max( f[x][1], f[v][0]+f[x][1]), f[v][0]);
f[x][0]=max( max( f[x][0], f[v][1]+f[x][0]), max( f[v][1], f[v][0]);
#include<cstdio>
#define N 6005
using namespace std;
struct Edge{int next,son;}edge[N];
int n,r[N],n_e,head[N],root,f[N][2];
bool rt[N];
inline int max(const int x,const int y);
int dp(int x);
inline void addedge(int fa,int son);
void init();
int main()
{
init();
dp(root);
printf("%d",max(f[root][1],f[root][0]));
return 0;
}
void init()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&f[i][1]);
for(int i=1;i<n;i++)
{
int l,k;
scanf("%d%d",&l,&k);
rt[l]=1;
addedge(k,l);
}
for(int i=1;i<=n;i++)
if(!rt[i])
{
root=i;
break;
}
}
inline void addedge(int fa,int son)
{
edge[++n_e].next=head[fa];
edge[n_e].son=son;
head[fa]=n_e;
}
int dp(int x)
{
for(int i=head[x];i;i=edge[i].next)
{
int v=edge[i].son;
dp(v);
f[x][1]=max(max(f[x][1],f[v][0]+f[x][1]),f[v][0]);
f[x][0]=max(max(f[x][0],f[v][1]+f[x][0]),max(f[v][1],f[v][0]));
}
}
inline int max(const int x,const int y)
{
return x>y?x:y;
}

浙公网安备 33010602011771号