又是一道树形DP的入门题,思想非常简单 然而我最开始还是存了两个状态[传送门]
题目描述
小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题。一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题。于是当日课后,小明就向老师提出了这个问题:
一株奇怪的花卉,上面共连有NN朵花,共有N-1N−1条枝干将花儿连在一起,并且未修剪时每朵花都不是孤立的。每朵花都有一个“美丽指数”,该数越大说明这朵花越漂亮,也有“美丽指数”为负数的,说明这朵花看着都让人恶心。所谓“修剪”,意为:去掉其中的一条枝条,这样一株花就成了两株,扔掉其中一株。经过一系列“修剪“之后,还剩下最后一株花(也可能是一朵)。老师的任务就是:通过一系列“修剪”(也可以什么“修剪”都不进行),使剩下的那株(那朵)花卉上所有花朵的“美丽指数”之和最大。
老师想了一会儿,给出了正解。小明见问题被轻易攻破,相当不爽,于是又拿来问你。
输入输出格式
输入格式:
第一行一个整数N(1 ≤ N ≤ 16000)N(1≤N≤16000)。表示原始的那株花卉上共NN朵花。
第二行有NN个整数,第II个整数表示第II朵花的美丽指数。
接下来N-1N−1行每行两个整数a,ba,b,表示存在一条连接第aa 朵花和第bb朵花的枝条。
输出格式:
一个数,表示一系列“修剪”之后所能得到的“美丽指数”之和的最大值。保证绝对值不超过21474836472147483647。
样例输入:
7
-1 -1 -1 1 1 1 0
1 4
2 5
3 6
4 7
5 7
6 7
样例输出:
3
如你所见这是一道背景略显智障非常好的题,我们来简化一下题目:
给定一个多叉树,每个点有一个权值。现在要做的就是保留或者不保留每个点,并且如果A是B和C的父节点,如果不保留A,那么B和C也不能保留。
那么我们需要求的就是最后能够保留的最大值。
于是最开始我是这么想的用f[u][0/1]来表示u节点的去留时所在子树的最大值,然后我弄完之后,因为智障而搞错了答案的存储,然后debug后突然想。。。既然0表示不选,那我为什么还要定义一个状态?????看来是我沙雕了。
那么既然定义出来了,就非常容易想到代码,代码如下:
1 #include2 #define Add(X,Y) add((X),(Y)),add((Y),(X)) 3 #define INF 1<<31 4 namespace Jason{ 5 #define Xuxp(X,Y,Z) for(int (X)=(Y);(X)<=(Z);++i) 6 #define Xuxs(X,Y,Z) for(int (X)=(Y);(X)>=(Z);--i) 7 inline void scan(int &x){ 8 int f=1;x=0;char s=getchar(); 9 while(s<'0' || s>'9'){if(s=='-') f=-1;s=getchar();} 10 while(s>='0' && s<='9'){x=x*10+s-'0';s=getchar();} 11 x*=f; 12 } 13 inline void print(int x){ 14 if(x<0){putchar('-');x=-x;} 15 if(x>9)print(x/10);char s=x%10+'0'; 16 putchar(s); 17 } 18 } 19 using namespace std; 20 using namespace Jason; 21 const int maxn=16000+5; 22 //-------------------- 23 struct Edge{ 24 int to,nxt; 25 }edge[maxn<<1];int cnt=0,head[maxn]; 26 int n,f[maxn]; 27 //-------------------- 28 inline void add(int x,int y) 29 { 30 edge[++cnt].nxt=head[x]; 31 edge[cnt].to=y; 32 head[x]=cnt; 33 } 34 inline void dp(int u,int fa) 35 { 36 for(int i=head[u];i!=-1;i=edge[i].nxt) 37 { 38 int v=edge[i].to; 39 if(v==fa) continue; 40 dp(v,u); 41 f[u]+=max(f[v],0); 42 } 43 } 44 int main() 45 { 46 int a,b; 47 memset(head,-1,sizeof(head)); 48 scan(n); 49 Xuxp(i,1,n) scan(f[i]); 50 Xuxp(i,1,n-1) scan(a),scan(b),Add(a,b); 51 dp(1,0); 52 int Max=-INF; 53 for(int i=1;i<=n;++i) if(f[i]>Max) Max=f[i]; 54 print(Max); 55 return 0; 56 }
QAQ
【正在纠结买不买无限正义高达。。。。。。。】