树形DP——Luogu2014 选课
来源:互联网 发布:守望先锋 伤害数据 编辑:程序博客网 时间:2024/06/05 21:15
题面:传送门
首先显然的这个树形结构的东西是一个森林
我们随便搞一个超级汇点变成一棵树好了
然后问题来了,这棵树是多叉树……
我想的状态是这样的:f[i][j]表示在以i节点为根的子树内取j个(符合题意)的最大值
转移的时候把子树内的转移到这棵子树的根即可,只不过这个根必选
可惜的是如果按照多叉树来转移的话转移会很麻烦。。。
所以只能多叉转二叉了,也就是说左儿子右兄弟
然后就可以用上面转移的方法转移了
对于超级汇点来说,因为按照上面转移,超级汇点也必须选上(你也可以特判)
所以最后答案是f[超级汇点][m+1]
#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<iostream>#include<cstdlib>#include<queue>#include<climits>#include<ctime>#include<string>using namespace std;int n,m,ls[100001],rs[100001],v[100001],s[100001];int nedge=0,p[100001],nex[100001],head[100001];int f[310][310];inline void addedge(int a,int b){ p[++nedge]=b;nex[nedge]=head[a];head[a]=nedge;}inline void dfs(int x){//多叉转二叉 int k=head[x]; if(!k)return; ls[x]=p[k];dfs(p[k]); int pp=p[k]; for(k=nex[k];k;k=nex[k]){ rs[pp]=p[k];dfs(p[k]); pp=p[k]; }}inline void dp(int x){//树形DP if(!x)return; dp(ls[x]),s[x]+=s[ls[x]]; dp(rs[x]),s[x]+=s[rs[x]]; s[x]++; for(int i=1;i<=s[x];i++){ f[x][i]=i>s[rs[x]]?0:f[rs[x]][i]; for(int j=0;j<=min(s[ls[x]],i-1);j++){ if(i-j-1>s[rs[x]])continue; int l=f[ls[x]][j],r=f[rs[x]][i-j-1]; f[x][i]=max(f[x][i],l+r+v[x]); } }}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ int x;scanf("%d%d",&x,&v[i]); if(x==0)x=n+1; addedge(x,i); } dfs(n+1);dp(n+1); printf("%d",f[n+1][m+1]); return 0;}
阅读全文
1 0
- 树形DP——Luogu2014 选课
- 【codevs1378】选课 树形DP
- 选课 树形DP
- 选课_ctsc1997_ssl1606_树形dp
- codevs1378 选课 树形dp
- 树形dp:选课
- codevs1378 选课-树形dp
- 选课(树形DP)
- Tyvj 1051 选课 树形dp
- [CODEVS1378]选课(树形dp)
- vijos P1180 选课 树形dp
- Vijos 1180 选课 [树形dp]
- 树形dp-洛谷 P2014 选课
- Codevs 1378 选课 树形DP
- 树形DP 洛谷P2014 选课
- bsoj 1660 选课(树形DP)
- Codevs_P1378 选课(树形DP+分组背包)
- code vs 1378 选课(树形DP)
- mysql主从复制(超简单)
- 我的mongoDB笔记
- 提高XCode运行速度的方法
- Java虚拟机之Java内存区域划分
- 三极管工作原理分析,精辟、透彻,看后你就懂
- 树形DP——Luogu2014 选课
- 深入理解Objective-C:Category
- 漂亮实用的提示框插件SweetAlert
- 没有针对多指触控处理版本与多指触控处理版本
- 那些让我难以忘记的TED演讲
- linux环境内存分配原理 mallocinfo
- 设计模式之访问者模式
- SpringMVC基础
- NSTimer的使用