树形背包。DP递推的思路很简单....

但是由于节点有15万个,先不论空间复杂度,这样开dp数组 dp[150000+10][300+10],如果初始化是memset(dp,-1,sizeof dp),则必然超时。

所以需要一个状态数剪枝。。。即记录这个节点最多组合的数量。

UVALive是不限制内存的,所以dp[150000+10][300+10] 能够AC,HDU 4169 限制了内存大小,需要优化空间复杂度。

内存优化之后的代码,HDU上C++能AC,G++依旧MLE。

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std; const int maxn=+;
struct Node
{
int val;
int fa;
queue<int *>Q;
vector<int>f;
}node[maxn];
int n,k,root;
int cnt[maxn];
int ans; void init()
{
memset(cnt,,sizeof cnt);
for(int i=;i<=n;i++)
{
while(!node[i].Q.empty()) node[i].Q.pop();
node[i].f.clear();
}
} void read()
{
for(int i=;i<=n;i++)
{
scanf("%d%d",&node[i].fa,&node[i].val);
if(!node[i].fa) root=i;
else node[node[i].fa].f.push_back(i);
}
} void dfs(int now)
{
if(!node[now].f.size())
{
cnt[now]=;
int *p=new int[cnt[now]+];
p[]=; p[]=node[now].val;
node[node[now].fa].Q.push(p);
delete[] p;
return;
} for(int i=;i<node[now].f.size();i++)
{
int id=node[now].f[i];
cnt[now]=cnt[now]+cnt[id];
} cnt[now]=min(k,cnt[now]); int *p=new int[cnt[now]+]; p[]=;
for(int i=;i<=cnt[now];i++) p[i]=-; int id=;
while(!node[now].Q.empty())
{
int *head=node[now].Q.front();
node[now].Q.pop(); for(int j=cnt[now];j>=;j--)
for(int s=;s<=j&&s<=cnt[node[now].f[id]];s++)
if(head[s]!=-&&p[j-s]!=-)
p[j]=max(p[j],head[s]+p[j-s]);
id++;
}
p[]=max(p[],node[now].val); node[node[now].fa].Q.push(p); if(now==)
{
if(cnt[]<k||p[k]==-) ans=-;
else ans=p[k];
} delete[] p;
return;
} void work()
{
dfs(root);
if(ans==-) printf("impossible\n");
else printf("%d\n",ans);
} int main()
{
while(~scanf("%d%d",&n,&k))
{
init();
read();
work();
}
return ;
}

二维DP写法。HDU 上MLE的。UvaLive能过的。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; int n, k;
int root;
const int maxn = + ;
struct Edge
{
int now;
int next;
}e[maxn];
int head[maxn];
int cnt[maxn];
int val[maxn];
int dp[maxn][ + ];
int q; void init()
{
q=;
for(int i=;i<=n;i++) head[i]=-;
} void read()
{
for (int i = ; i <= n; i++)
{
int fa;
scanf("%d%d", &fa, &val[i]);
if (!fa) root = i;
else
{
e[q].now=i, e[q].next=head[fa];
head[fa]=q, q=q+;
}
}
} void dfs(int now)
{
cnt[now]=;
if (head[now]==-)
{
cnt[now]=;
dp[now][] = val[now];
return;
} for (int i = head[now]; i!=-; i=e[i].next)
{
int id = e[i].now;
dfs(id);
cnt[now]=cnt[now]+cnt[id];
} cnt[now]=min(cnt[now],k); for(int i=;i<=cnt[now];i++) dp[now][i]=-;
dp[now][]=; for (int i = head[now]; i!=-; i=e[i].next)
{
int id = e[i].now;
for(int j=cnt[now];j>=;j--)
for(int s=;s<=j&&s<=cnt[id];s++)
if(dp[id][s]!=-&&dp[now][j-s]!=-)
dp[now][j]=max(dp[now][j],dp[id][s]+dp[now][j-s]);
}
dp[now][]=max(val[now],dp[now][]);
} void work()
{
dfs(root);
if (cnt[root]<k||dp[root][k] == -) printf("impossible\n");
else printf("%d\n", dp[root][k]);
} int main()
{
while (~scanf("%d%d", &n, &k))
{
init();
read();
work();
}
return ;
}

HDU 4169 UVALive 5741 Wealthy Family的更多相关文章

  1. HDU 4169 Wealthy Family(树形DP)

    Problem Description While studying the history of royal families, you want to know how wealthy each ...

  2. HDU 4169 树形DP

    Wealthy Family Problem Description While studying the history of royal families, you want to know ho ...

  3. hdu 4169 二分匹配最大独立集 ***

    题意:有水平N张牌,竖直M张牌,同一方向的牌不会相交.水平的和垂直的可能会相交,求最少踢出去几张牌使剩下的牌都不相交. 二分匹配 最小点覆盖=最大匹配. 链接:点我 坐标点作为匹配的端点 #inclu ...

  4. HDU 5741 Helter Skelter(构造法)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5741 [题目大意] 一个01相间的串,以0开头,给出的序列每个数字表示连续的0的个数或者1的个数, ...

  5. POJ 3342 Party at Hali-Bula / HDU 2412 Party at Hali-Bula / UVAlive 3794 Party at Hali-Bula / UVA 1220 Party at Hali-Bula(树型动态规划)

    POJ 3342 Party at Hali-Bula / HDU 2412 Party at Hali-Bula / UVAlive 3794 Party at Hali-Bula / UVA 12 ...

  6. POJ 1087 A Plug for UNIX / HDU 1526 A Plug for UNIX / ZOJ 1157 A Plug for UNIX / UVA 753 A Plug for UNIX / UVAlive 5418 A Plug for UNIX / SCU 1671 A Plug for UNIX (网络流)

    POJ 1087 A Plug for UNIX / HDU 1526 A Plug for UNIX / ZOJ 1157 A Plug for UNIX / UVA 753 A Plug for ...

  7. POJ 1511 Invitation Cards / UVA 721 Invitation Cards / SPOJ Invitation / UVAlive Invitation Cards / SCU 1132 Invitation Cards / ZOJ 2008 Invitation Cards / HDU 1535 (图论,最短路径)

    POJ 1511 Invitation Cards / UVA 721 Invitation Cards / SPOJ Invitation / UVAlive Invitation Cards / ...

  8. UVALive - 4223(hdu 2926)

    ---恢复内容开始--- 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2962 Trucking Time Limit: 20000/10000 MS ...

  9. HDU 5741 Helter Skelter

    离线处理+扫描线.题意很容易转化:若干个矩形形成并集,询问一些点是否在并集中? 官方题解不是这样做的....那种做法效率更高,暂时还不会.我这样是4500ms G++过的,C++TLE...... 区 ...

随机推荐

  1. linux的学习系列 4---文件权限和访问模式

    为了更加安全的存储文件,Linux为不同的文件赋予了不同的权限,每个文件都拥有下面三种权限: 所有者权限:文件所有者能够进行的操作 组权限:文件所属用户组能够进行的操作 外部权限(其他权限):其他用户 ...

  2. SCRIPT7002: XMLHttpRequest: 网络错误 0x2ef3, 由于出现错误 00002ef3&nbsp

    项目使用的是tomcat7 ,浏览器是ie11 突然打开浏览器发现不能获取数据了 tomcat conf server.xml 文件 <Connector port="8080&quo ...

  3. 关于SVN更新注意

    SVN更新时其实大部分都可以直接更新但是只有在 当然为0就没有事但是如果不是0的话就要注意了表示你修改的和别人修改了相同的文件先点开 次文件然后看看那些不一样主要看如果是这样就直接点更新就好了,如果有 ...

  4. 2015年4月29日 dayofweek

    #include <stdio.h>#include <stdlib.h>int DayofYear(int year, int month, int day);#define ...

  5. A SPI class of type org.apache.lucene.codecs.PostingsFormat with name 'Lucene40' does not exist.

    简单的建立索引和查询索引并不难,关键在于他的二次开发,让他适合你自己的需求 既然要二次开发就必须查看源码 首先看看索引过程中的核心类吧: IndexWriter 这个是核心组件, 建立和打开索引,以及 ...

  6. java 文件字符输入、输出流

    Example10_6.java import java.io.*; public class Example10_6 { public static void main(String args[]) ...

  7. Extjs视频

    Extjs视频http://www.youku.com/playlist_show/id_19343298.html ExtJs视频教程(关东升) 智捷关东升老师ExtJs视频教程AJAX框架-Ext ...

  8. IDL 实现PCA算法

    在多元统计分析中,主成分分析(Principal components analysis,PCA)是一种分析.简化数据集的技术.主成分分析经常用于减少数据集的维数,同时保持数据集中的对方差贡献最大的特 ...

  9. L7,too late

    words: parcel,包裹 detective,侦探 expect,期待 airfield,飞机起落的场地 guard,警戒,守卫,n precious,adj,珍贵的 stone,石头 exp ...

  10. 手机号码抽奖系统(JS)

    <html><head><title>手机号码抽奖</title><meta http-equiv="Content-Type" ...