目录
D - TT 的苹果树
题意
在大家的三连助攻下,TT 一举获得了超级多的猫咪,因此决定开一间猫咖,将快乐与大家一同分享。并且在开业的那一天,为了纪念这个日子,TT 在猫咖门口种了一棵苹果树。
一年后,苹果熟了,到了该摘苹果的日子了。
已知树上共有 N 个节点,每个节点对应一个快乐值为 w[i] 的苹果,为了可持续发展,TT 要求摘了某个苹果后,不能摘它父节点处的苹果。
TT 想要令快乐值总和尽可能地大,你们能帮帮他吗?
思路
此题与“没有上司的舞会”极为相似,利用树型dp求解。
设状态f[i][0]为以i为子树且未选择i节点,f[i][1]为以i为子树且选择了i节点。转移方程为
其中求和对象是i节点的所有子节点。
实际编程过程中还要对树结构进行处理,得到正确的dp顺序。采用的方法是层次遍历整棵树,以遍历结果的逆序来动归。
代码
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct node;
struct link{
link* next;
int id;
};
struct node{
int w;
link* child;
int pa;
void add(int v){
link* p=new link;
p->id=v;
p->next=child;
child=p;
}
void clear(){
link*p,*q;
p=child;
while(p!=NULL){
q=p;
p=p->next;
delete q;
}
child=NULL;
pa=-1;
}
};
node apple[6005];
int f[6005][3];
int N;
struct unit{
int level;
int id;
unit(int l,int i){
level=l;
id=i;
}
};
vector<unit> V;
queue<int> Q;
void scanTree(){
V.clear();
while(!Q.empty())Q.pop();
int p=1;
while(apple[p].pa!=-1)p=apple[p].pa;
int thisL,nextL,cotL;
thisL=nextL=cotL=0;
Q.push(p);
thisL++;
while(!Q.empty()){
int thisNode=Q.front();
Q.pop(