P2015 二叉苹果树
Posted For_Miku
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2015 二叉苹果树相关的知识,希望对你有一定的参考价值。
----------------
链接:Miku
----------------
这道题的dp还是先更新子节点,在更新父节点,不过问题就是怎样更新他们
我们定义ff[i][j]为第i个节点字数上共保留j条边的情况下最多的苹果数,对于每一个点,他保留的边必然是他直接保留的之前保留的边和他当前儿子保留的边的值的和加上这一条边的
边权,即ff[u][i]=max(ff[u][i],f[u][i−j−1]+ff[v][j]+e[i].w)( 1≤i≤min(q,son[u]),0≤j≤min(son[v],i−1) )
然后不断递归更新即可
----------------
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #define ll long long const int maxn=105; using namespace std; int n,m,ff[maxn][maxn]; struct b{ int to; int ne; int w; }e[maxn*2]; int p; int head[maxn]; void add(int f,int to,int w){ p++; e[p].ne=head[f]; e[p].to=to; e[p].w=w; head[f]=p; } int x,y,z; int son[maxn]; void dfs(int now,int f){ for(int i=head[now];i;i=e[i].ne){ int v=e[i].to; if(v==f) continue; dfs(v,now); son[now]+=son[v]+1; for(int j=min(son[now],m);j;--j ){//我们就能取这些了 for(int k=min(son[v],j-1);k>=0;k--){//考虑一下怎么分配要保留的边 ff[now][j]=max(ff[now][j],ff[now][j-k-1]+ff[v][k]+e[i].w);//记得减一,不然我们就和这个v断开了联系 } } } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<n;++i){ scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } dfs(1,-1);//根节点是谁不重要 printf("%d",ff[1][m]); return 0; }
以上是关于P2015 二叉苹果树的主要内容,如果未能解决你的问题,请参考以下文章