打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Tree of tree

题意:
一棵结点带权树,大小(结点数)为k的子树的权值和最大为多少。

初步分析
这道题其实就是一道01背包问题只是是在树上做而已。背包的总容量就是k个结点(一定得刚好装满),每个物品的价值就是结点的权值w[i].注意,并不是随便选取结点就行了。而是一定得是子树。那么这一点我们要怎么实现呢。首先我们用dp[i][j]来表示以结点i为首的结点数为j的权值最大的一棵子树。那么dp[i][j]的状态方程怎么写呢?dp[i][j]=max(dp[i][j],dp[i][j-w] dp[v][w])(v是结点i的子节点,1=<j<=cnt[i],0<w<j)注意我们是怎么保证dp[i][j]表示的是以结点i为首的子树呢?新节点所能取得的最大结点数只能是j-1,因为dp[i][1]始终代表的是结点i,所以才能保证都是以结点i为首的子树。而且由于是01背包所以我们的背包容量j从大到小更新,这样保证所有的小值都是上一次子节点的更新值而不是重复使用当前结点的值(不然的话就变成完全背包了)。

直接上代码

#include <iostream>#include <string.h>using  namespace std;const int MAX_N=110;const int MAX_M=220;int w[MAX_N];int dp[MAX_N][MAX_N];int cnt[MAX_N];int n,k,answer=0;//我们这里用图来储存树,在遍历的时候通过一个father参数就可以转化为树了。没有必要用一个father数组来储存int ans=0;int head[MAX_N];struct edge{    int v;    int next;}eid[MAX_M];void insert(int u,int v){    eid[ans].v=v;    eid[ans].next=head[u];    head[u]=ans  ;}int read(){    int w=1,s=0;    char ch=getchar();    while(!isdigit(ch)){        if(ch=='-'){           w*=-1;        }        ch=getchar();    }    while(isdigit(ch)){        s=(s<<1) (s<<3) ch-48;        ch=getchar();    }    return s*w;}int dfs(int node,int father){    cnt[node]=1;    for(int i=head[node];i!=-1;i=eid[i].next){        int v=eid[i].v;        if(v==father) continue;        cnt[node] =dfs(v,node);    }    dp[node][1]=w[node];    for(int i=head[node];i!=-1;i=eid[i].next){        int v=eid[i].v;        if(v==father) continue;        for(int j=cnt[node];j>=1;--j) {            for (int m = 0; m <=cnt[v] && m<j ;   m) {                dp[node][j] = max(dp[node][j], dp[node][j - m] dp[v][m]);            }        }    }    answer=max(answer,dp[node][k]);    return cnt[node];}int main() {    while(scanf("%d %d",&n,&k)!=EOF) {        for (int i = 1; i <= n;   i) {            w[i] = read();        }        memset(head, -1, sizeof(head));        ans=0;        for (int i = 0; i <MAX_N;   i) {            for (int j = 0; j <MAX_N;   j) {                dp[i][j] = 0;            }        }        for (int i = 1; i <= n - 1;   i) {            int x, y;            x = read() 1;            y = read() 1;            insert(x, y);            insert(y, x);        }        dfs(1, -1);        cout <<answer<<endl;        answer=0;    }    return 0;}
来源:https://www.icode9.com/content-4-386351.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
​LeetCode刷题实战298:二叉树最长连续序列
算法连载(3)--生成最优归并树
C语言实现哈夫曼编码与译码
数据结构_哈弗曼树的编译码_课程设计_实验报告
Prim 算法及其高效实现
赫夫曼编码
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服