zoukankan      html  css  js  c++  java
  • hdu4169 Wealthy Family (树形背包)

    题意:给定一棵树,每一节点都有一权值,要求选出总权值最大的K个点,同时这K个点中任意一个点都不能是其他节点的祖先。。

    分析:呵呵,一看到题目就感觉是一个树形背包了,可是节点数太多了,150000,吃不消呀,如果用二维数组保存的话,很好写呀,可是肯定爆内存的,所以开了一个临时数组保存

    模型跟一般的树形背包还是很像的

    View Code
    #include<algorithm>
    #include<vector>
    #include<iostream>
    using namespace std;
    const int N = 150010;
    vector<int> g[N];
    int n,dp[310],K,w[N];
    void init()
    {
    for(int i=0;i<=n;i++)
    g[i].clear();
    }
    int dfs(int u)
    {
    int size=g[u].size();
    int t=0;//保存当前子树已产生的状态数
    int cur[310];//保存当前子树的背包状态
    for(int i=1;i<=K;i++)
    dp[i]=cur[i]=-INT_MAX;
    cur[0]=dp[0]=0;
    for(int i=0;i<size;i++)
    {
    int v=g[u][i];
    int now=dfs(v);//找出v分支的状态数,同时将背包状态保存在dp数组中
    for(int j=t;j>=0;j--)//当前子树已产生的状态数
    {
    for(int k=1;k<=now;k++)//v节点遍历的子树产生的状态数
    {
    if(k+j>K)
    break;
    cur[k+j]=max(cur[k+j],dp[k]+cur[j]);
    }
    }
    t+=now;//俩部分组合完之后再将v分支的状态数加到当前子树上
    }
    if(size==0) //因为少了这一步判断,WA了一晚…… ,因为父节点是在儿子的状态数组合完之后再跟cur[1]比较判断,不产生状态数,只有当当前节点是叶子节点是,t才需要累加
    t++;
    cur[1]=max(cur[1],w[u]);//注意,根节点要等整个子树做完背包之后,再加入,因为,父节点不能加入子节点不能同时加入背包
    for(int i=0;i<=K;i++)//将当前子树的状态保存到dp数组中
    dp[i]=cur[i];
    return t;//返回当前子树产生的状态总数
    }
    int main()
    {
    int x,root;
    while(scanf("%d %d",&n,&K)==2)
    {
    init();
    for(int i=1;i<=n;i++)
    {
    scanf("%d %d",&x,&w[i]);
    if(x==0)
    root=i;//找出根节点
    else
    g[x].push_back(i);
    }
    dfs(root);
    if(dp[K]==-INT_MAX)
    printf("impossible\n");
    else printf("%d\n",dp[K]);
    }
    return 0;
    }
  • 相关阅读:
    socket注意
    PCM音频文件编码
    题外:分类篇(音乐风格分类)基于BP神经网络
    MFCC特征提取过程详解
    语音信号分析
    k-means聚类
    c++关键字详解
    vs中项目解决方案和项目的关系
    条件编译#ifdef 和#endif
    c++快捷键
  • 原文地址:https://www.cnblogs.com/nanke/p/2379261.html
Copyright © 2011-2022 走看看