树形背包。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. JUST SORT

    We define B is a Divisor of one number A if A is divisible by B. So, the divisors of 12 are 1, 2, 3, ...

  2. tiny210移植linux内核(3.0.8)杂项

    关于三星芯片nand内存分区文件: linux-3.0.8/drivers/mtd/nand/s3c_nand.c struct mtd_partition s3c_partition_info[] ...

  3. ubuntu 常用命令记录

    1.# 表示权限用户(如:root),$ 表示普通用户  开机提示:Login:输入用户名  password:输入口令   用户是系统注册用户成功登陆后,可以进入相应的用户环境.  退出当前shel ...

  4. js 基础对象二

    大的分类 JavaScript 对象 JS Array JS Boolean JS Date JS Math JS Number JS String JS RegExp JS Functions JS ...

  5. android性能优化优秀文章

    郭霖最近整理的文章: 合理管理内存 分析编码过程中如何避免过多内存占用,以及如何实现高性能的内存使用. 尽可能使用intentService; 当界面不可见时释放内存; 当内存紧张时释放内存; 避免b ...

  6. IP地址、子网掩码详解

    如何通过子网掩码划分网段 资料一: 一.缺省A.B.C类地址,子网掩码:  二.子网掩码的作用:  code:  IP地址 192.20.15.5 11000000 00010100 00001111 ...

  7. 【摘自网络】dll库和lib库有什么区别

    简单地讲:第一:.DLL是动态链接库,而.LIB是静态链接库dll是个编译好的程序,调用时可以直接调用其中的函数,不参加工程的编译. 而lib应该说是一个程序集, 只是把一些相应的函数总结在一起, 如 ...

  8. cs的变态语法

    int? a = null; //?指示a为可空checked { ... } //赋值溢出抛异常unchecked { ... } //赋值溢出不抛异常expr1??expr2 //空结合运算符,e ...

  9. Android中监听webview监听是否加载完成

    之前写过一篇捕获Phoengap的webview事件的方法,主要是在实现了CordovaInterface的Activity中,  在onMessage中根据第一个参数的message name来判断 ...

  10. HDU-5289<two pointers>

    题意: 求一个数列中存在多少个区间,每个区间内的数的差不超过k; 思路:two_pointers; #include<iostream> #include<cstdio> #i ...