[树形依赖多重背包] BZOJ 4910 [Sdoi2017] 苹果树
2017-06-09 14:36
267 查看
首先解决依赖背包
如果是0/1背包,按照后序遍历dp,根据选或不选决策
现在是多重背包,那么这个点只留一个,剩下的变成一个新点挂上去,这样仍然满足依赖关系,
转移的时候多重背包用单调对列优化
可以发现如果除了最长的一条链,剩余最多K个
因为权值为正 那么最长链必然连到叶子,剩余必然取K个(除非不足K个)
那么我们枚举叶子 然后两边总共取出K个,枚举两边分别选几个
两边需要两次儿子顺序不同的后序遍历
复杂度O(nK)
被卡常,我把部分分特判了才过TAT
如果是0/1背包,按照后序遍历dp,根据选或不选决策
现在是多重背包,那么这个点只留一个,剩下的变成一个新点挂上去,这样仍然满足依赖关系,
转移的时候多重背包用单调对列优化
可以发现如果除了最长的一条链,剩余最多K个
因为权值为正 那么最长链必然连到叶子,剩余必然取K个(除非不足K个)
那么我们枚举叶子 然后两边总共取出K个,枚举两边分别选几个
两边需要两次儿子顺序不同的后序遍历
复杂度O(nK)
被卡常,我把部分分特判了才过TAT
#include<cstdio> #include<cstdlib> #include<algorithm> #include<vector> #include<cstring> #define cl(x) memset(x,0,sizeof(x)) #define pb push_back using namespace std; typedef long long ll; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=40005; const int KK=500005; const int NK=51000000; struct edge{ int u,v,next; }G[N<<1]; int head ,inum; inline void add(int u,int v,int p){ G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p; } int a ,v ; #define V G[p].v int n,K; int ncnt,pos ; int lst1 ,lst2 ,pnt; int pre1 ,pre2 ,back1 ,back2 ; int size ; int f1[NK],f2[NK]; int leaf ; int val ,depth ; inline void dfs1(int u){ pre1[u]=pnt+1; size[u]=1; for (int p=head[u];p;p=G[p].next){ val[V]=val[u]+v[V],depth[V]=depth[u]+1; dfs1(V); size[u]+=size[V]; } lst1[++pnt]=u; back1[u]=pnt; } inline void dfs2(int u){ pre2[u]=pnt+1; vector<int> v; for (int p=head[u];p;p=G[p].next) v.pb(V); for (int i=v.size()-1;~i;i--) dfs2(v[i]); lst2[++pnt]=u; back2[u]=pnt; } int Q[KK],l,r; int Q2[KK]; #define F(i,j) (ff[(i)*(K+1)+(j)]) inline int max(int a,int b){ return a>b?a:b; } inline void DP(int *ff,int *lst,int *pre){ F(0,0)=0; for (int k=1;k<=K;k++) F(0,k)=-1<<29; for (int i=1;i<=ncnt;i++){ int x=lst[i]; int *f=ff+i*(K+1),*g=ff+(i-1)*(K+1),*t=ff+(pre[x]-1)*(K+1); //for (int k=0;k<=K;k++) f[k]=t[k]; memcpy(f,t,sizeof(int)*(K+1)); if (a[x]==0) continue; if (a[x]==1){ for (int k=1;k<=K;k++) f[k]=max(f[k],g[k-1]+v[x]); }else{ l=r=-1; Q[++r]=0; Q2[r]=g[Q[r]]-Q[r]*v[x]; for (int j=1;j<=K;j++){ while (l<r && Q[l+1]<j-a[x]) l++; if (l<r) f[j]=max(f[j],Q2[l+1]+j*v[x]); int tmp=g[j]-j*v[x]; while (l<r && tmp>=Q2[r]) r--; Q[++r]=j; Q2[r]=tmp; } } } } namespace Work{ inline bool cmp(int x,int y){ return v[x]>v[y]; } int idx ; inline void Solve(){ for (int i=1;i<=n;i++) idx[i]=i,a[i]+=a[pos[i]]; a[1]--; int x=K+1,ans=v[1]; sort(idx+1,idx+n+1,cmp); for (int i=1;i<=n;i++){ int t=min(x,a[idx[i]]); x-=t; ans+=v[idx[i]]*t; if (!x) break; } printf("%d\n",ans); } } int main(){ int T; int x,y,z; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(T); while (T--){ read(n); read(K); ll tot=0; ncnt=n; int maxv=0; for (int i=1;i<=n;i++){ read(x); read(y); read(z); tot+=y; maxv=max(maxv,x); if (x) add(x,i,++inum),leaf[x]=1; v[i]=z; a[i]=1; if (y>1) pos[i]=++ncnt,v[ncnt]=z,a[ncnt]=y-1,add(i,ncnt,++inum); } if (maxv<=1){ Work::Solve(); cl(head); inum=0; cl(leaf); cl(pos); continue; } pnt=0; val[1]=v[1]; depth[1]=1; dfs1(1); DP(f1,lst1,pre1); pnt=0; dfs2(1); DP(f2,lst2,pre2); int ans=-1<<30; for (int i=1;i<=n;i++) if (!leaf[i]){ int *f=f1+(K+1)*(pre1[i]+size[i]-2); int *g=f2+(K+1)*(pre2[i]-1); int x=min(tot-depth[i],(ll)K); for (int k=0;k<=x;k++) ans=max(ans,val[i]+f[k]+g[x-k]); } printf("%d\n",ans); cl(head); inum=0; cl(leaf); cl(pos); } return 0; }
相关文章推荐
- [树上依赖多重背包 DP] BZOJ 4910 [Sdoi2017]苹果树
- [树上依赖背包] BZOJ4910 LOJ2268: [SDOI2017] 苹果树
- bzoj4753: [Jsoi2016]最佳团体(分数规划+树形依赖背包)
- bzoj 4813: [Cqoi2017]小Q的棋盘 [树形背包dp]
- 【bzoj2427】【软件安装】tarjan缩点+树形依赖背包
- BZOJ 2427 软件安装 (tarjan 树形依赖背包)
- BZOJ2427 浅谈TARJAN缩点 和 树形依赖背包动态规划
- 【bzoj2427】【软件安装】tarjan缩点+树形依赖背包
- BZOJ.4753.[JSOI2016]最佳团体(01分数规划 树形背包DP)
- HDU 1561 The more,The Better (树形DP+有依赖的背包问题)
- 【bzoj4818】 Sdoi2017—序列计数
- cqoi2017,bzoj4813小Q的棋盘(树形dp或瞎搞)
- BZOJ5333 [Sdoi2018]荣誉称号 【差分 + 树形dp】
- BZOJ 4816 [Sdoi2017]数字表格
- HDU 1011 Starship Troopers (树形DP+依赖背包)
- BZOJ4912 [Sdoi2017]天才黑客 【虚树 + 最短路】
- 【BZOJ 4818】【SDOI 2017】序列计数
- bzoj 1017: [JSOI2008]魔兽地图DotR【树形dp+背包】
- 【bzoj4816】[Sdoi2017]数字表格 莫比乌斯反演
- HDU 1561 The more, The Better - 依赖背包+树形dp基础