[JZOJ5426]摘Galo
2017-11-05 20:12
183 查看
题目大意:
有一棵n个结点的树,每个点都有一个权值,你要从中选出不超过k+1个点使得权值和尽量大。
同时要注意如果一个点被选择,那么它的子树和这个点到根结点路径上的点不能被选择。
思路:
很水的树形DP。
f[i][j]表示以i为根的子树中选择了j个点的最大权值和。
状态转移方程f[par[i]][k]=max{f[par[i]][k]+f[i][j]};
转移的时候可能会被覆盖掉,因此用一个临时数组g来保存。
for的时候不能for满,不然就变成O(nk^2)的了,只有60分。
数组可能会开不下,要用vector。
#include<cstdio> #include<cctype> #include<vector> typedef long long int64; inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x; } const int N=100001; int par ,w ,size ; std::vector<std::vector<int64> > f; std::vector<int64> g; int main() { const int n=getint(),k=getint()+1; for(register int i=2;i<=n;i++) { par[i]=getint(),w[i]=getint(); } f.resize(n+1); g.resize(k+1); for(register int i=1;i<=n;i++) size[i]=1; for(register int i=n;i>1;i--) { size[par[i]]+=size[i]; if(f[i].empty()) f[i].resize(k+1); if(f[par[i]].empty()) f[par[i]].resize(k+1); g=f[par[i]]; f[i][1]=std::max(f[i][1],(int64)w[i]); for(register int j=1;j<=std::min(size[i],k);j++) { for(register int l=0;l<=std::min(size[par[i]],k)-j;l++) { g[l+j]=std::max(g[l+j],f[par[i]][l]+f[i][j]); } } f[par[i]]=g; f[i].clear(); } int64 ans=0; for(register int i=0;i<=k;i++) ans=std::max(ans,f[1][i]); printf("%lld\n",ans); return 0; }
相关文章推荐
- JZOJ 5426. 【NOIP2017提高A组集训10.25】摘Galo
- JZOJ5426. 【NOIP2017提高A组集训10.25】摘Galo
- JZOJ 5426. 【NOIP2017提高A组集训10.25】摘Galo
- JZOJ 5426 Galo
- 【JZOJ 5426】【NOIP2017提高A组集训10.25】摘Galo
- 【JZOJ 4630】计数
- 【JZOJ4630】计数
- [JZOJ4637] 大鱼海棠(By--A_Crazy_Czy)
- [暑假集训] jzoj 2016.7.17 noip模拟赛C&B 总结
- JZOJ1444. 交换【推荐】
- jzoj 1359. 【2011.12普及模拟】数三角
- 【UOJ67】【JZOJ4679】种树
- jzoj 2544. 【NOIP2011模拟9.3】作弊的发牌者
- JZOJ 4686 通讯【NOIP2016提高A组8.12】
- jzoj 2553. 【NOIP2011模拟9.7】射命丸文
- jzoj 2567. 【NOIP2011模拟9.17】电话时间
- 【SCOI 2010】【JZOJ 4692】传送带
- JZOJ[8.16比赛]题解
- JZOJ4711. Binary
- {题解}[jzoj3084]【NOIP2012模拟11.3】超级变变变