博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P2014 选课
阅读量:6224 次
发布时间:2019-06-21

本文共 1325 字,大约阅读时间需要 4 分钟。

第一道树形dp。挺奇怪的。


这道题选择一个点是有一个先决条件,也就是要先选他父亲的点。

画出草图可以发现就是森林嘛。。。

利用网络流的思想,建立超级根结点,把以0为父亲的都连到root去。

树形dp较线性dp的不同之处就是要dp儿子。

所以在树上要dp之前先弄一下儿子,确保他已经被dp好了就可以了。

如何实现?dfs!

在dfs中套出这么一个板子就可以了。

树形dp老思路:

dp[i][j]为在第i个结点的子树中,选择j个结点的最大或最小花费。

然后一般就有:

dp[i][j] = dp[i][j - k] + dp[son][k]

k是在子树中弄的,所以从1到子树size-1。

因为类似于01背包,所以要逆序递推。

代码:

#include
#include
const int maxn = 3005;struct Edges{ int next, to;} e[maxn << 2];int head[maxn], tot;int n, m;int dp[maxn][maxn];int root;void link(int u, int v){ e[++tot] = (Edges){head[u], v}; head[u] = tot;}int dfs(int u){ int ans = 1; for(int i = head[u]; i; i = e[i].next) { int v = e[i].to; int t = dfs(v); ans += t; for(int j = ans; j > 0; j--) { for(int k = 0; k <= t; k++) { if(j - k > 0) dp[u][j] = std::max(dp[u][j], dp[u][j - k] + dp[v][k]); } } } return ans;}int main(){ //for(int i = 0; i < maxn; i++) for(int j = 0; j < maxn; j++) dp[i][j] = -19260817; scanf("%d%d", &n, &m); root = n + 1; for(int i = 1; i <= n; i++) { int k; scanf("%d%d", &k, &dp[i][1]); if(k == 0) k = root; link(k, i); } dfs(root); printf("%d\n", dp[root][m + 1]); return 0;}

转载于:https://www.cnblogs.com/Garen-Wang/p/9436780.html

你可能感兴趣的文章
5G时代,中国将彻底终结美国霸权!wifi和互联网也面临消失!
查看>>
人工智能技术将助力改善移动安全
查看>>
WPS Office Linux版本一年未更新:已中止开发
查看>>
云计算性能常见问题:云计算何处何从?
查看>>
优秀OA系统的五大特性
查看>>
线路愈加明晰?万达牵手IBM进军公有云业务
查看>>
【转】Zookeeper-Watcher机制与异步调用原理
查看>>
纽约州推出“被遗忘权”提案 用户或能要求将个人隐私信息从搜索结果中移
查看>>
降低测试难度及成本 加速物联网普及
查看>>
融入欧洲产业链 华为在数学上投注希望
查看>>
中国实现城域量子隐形传态为全球量子网络打基础
查看>>
超算入云
查看>>
沃达丰完成5G毫微波测试 室外单用户速率达到20Gbps
查看>>
Facebook宣布支持在Android上使用Tor访问
查看>>
即便背靠微信,微信企业号累积 2000 万用户也用了近两年时间
查看>>
MuleSoft发布新的Anypoint Platform,用户可操控API
查看>>
牙疼怎么快速止痛,三招解决牙痛立竿见影
查看>>
大数据云计算悄然改变服务器市场格局 英特尔霸主地位受IBM、ARM威胁
查看>>
英利宣布退出欧盟限价限协议
查看>>
深圳运用大数据推动"智慧司法"
查看>>