[樹形依賴多重揹包] BZOJ 4910 [Sdoi2017] 蘋果樹
首先解決依賴揹包
如果是0/1揹包,按照後序遍歷dp,根據選或不選決策
現在是多重揹包,那麼這個點只留一個,剩下的變成一個新點掛上去,這樣仍然滿足依賴關係,
轉移的時候多重揹包用單調對列優化
可以發現如果除了最長的一條鏈,剩餘最多
因為權值為正 那麼最長鏈必然連到葉子,剩餘必然取
那麼我們列舉葉子 然後兩邊總共取出
兩邊需要兩次兒子順序不同的後序遍歷
複雜度
被卡常,我把部分分特判了才過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[N],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[N],v[N];
#define V G[p].v
int n,K;
int ncnt,pos[N];
int lst1[N],lst2[N],pnt;
int pre1[N],pre2[N],back1[N],back2[N];
int size[N];
int f1[NK],f2[NK];
int leaf[N];
int val[N],depth[N];
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[N];
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;
}
相關推薦
[樹形依賴多重揹包] BZOJ 4910 [Sdoi2017] 蘋果樹
首先解決依賴揹包 如果是0/1揹包,按照後序遍歷dp,根據選或不選決策 現在是多重揹包,那麼這個點只留一個,剩下的變成一個新點掛上去,這樣仍然滿足依賴關係, 轉移的時候多重揹包用單調對列優化 可以發現如果除了最長的一條鏈,剩餘最多K個 因為權值為正 那
[樹上依賴多重揹包 DP] BZOJ 4910 [Sdoi2017]蘋果樹
題目 t−h≤k 的限制其實就是選一條到葉節點的鏈,然後再選k個的最大值(因為vi都大於零)。 因為 ai>1 的點,肯定是先選了第一個才會選第二個 所以可以把 ai>1 的點拆成兩個點 i′,i′′,ai′=1,ai′′=ai−1,讓 i′′
JZOJ4202. Shopping(點分治+樹形依賴+多重揹包)
題意: 一顆樹,每個點代表一個物品,空間c[i]c[i],數量d[i]d[i],價值w[i]w[i],現有一個空間為mm的揹包,選樹上相互連線的物品,求最大價值 想法: 一眼樹形揹包,時間複雜度上天 f[i][j]f[i][j]表示i的子樹內,i
BZOJ.4910.蘋果樹(樹形依賴揹包 DP 單調佇列)
BZOJ 洛谷 \(shadowice\)已經把他的思路說的很清楚了,可以先看一下會更好理解? 這篇主要是對\(Claris\)題解的簡單說明。與\(shadowice\)的做法還是有差異的(比如並沒有明顯用到後序遍歷的性質),而且用這種寫法可能跑的比較輕鬆? 問題等價於樹形依賴揹包,允許一條鏈每個
BZOJ.3425.[POI2013]Polarization(DP 多重揹包)
BZOJ 洛谷 最小可到達點對數自然是把一條路徑上的邊不斷反向,也就是黑白染色後都由黑點指向白點。這樣答案就是\(n-1\)。 最大可到達點對數,容易想到找一個點\(a\),然後將其子樹分為兩部分\(x,y\),\(x\)子樹所有邊全指向\(a\),\(a\)與\(y\)子樹之間的邊全指向\(y\)。這樣答
bzoj 1812 [IOI2005] riv (樹形dp,樹上揹包)
這道題比較有難度。。。首先可以想到f[i][k]表示i點的子樹中用了k個伐木場。但是這顯然沒法轉移。那麼我們加上一維, f[i][j][k]表示i點的子樹內用了k個伐木場並且上一個用的位置為j,而當前點可選可不選(看第二維的狀態),之後用子樹更新即可 合併的時候和更新的時
洛谷 P2014 選課 樹形依賴揹包
題目描述 在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有N門功課,每門課有個學分,每門課有一
Codeforces 815 C 樹形依賴揹包 解題報告
C. Karen and Supermarket On the way home, Karen decided to stop by the supermarket to buy some groceries. She needs to buy a lot
BZOJ 4182 Shopping (樹分治+樹上多重揹包)
題目大意:給你一顆樹,你有$m$元錢,每個節點都有一種物品,價值為$w$,代價為$c$,有$d$個,如果在$u$和$v$兩個城市都購買了至少一個物品,那麼$u,v$路徑上每個節點也都必須買至少一個物品 單調佇列陣列開小了調了2h 通過這道題,本蒟蒻終於$get$到了樹上帶權揹包的正確姿勢 合併揹包的代價
【DP】計劃11.8——(樹形依賴揹包總結)&&分數規劃思想
樹形依賴揹包指的就是一類具有樹形依賴關係的揹包問題。當選一個物品的前提是選另一件物品,而這些依賴關係構成了一個樹形關係。在容量有限的情況下,然後求最大的價值,這類問題我們就稱之為樹形依賴揹包。 樹形依賴揹包問題實際上是一類分組揹包問題,我們可以將每個點的子樹看成
動態規劃--樹形依賴揹包
樹形依賴揹包是子樹依賴父親才能產生貢獻的一類問題。 有三種種解決的辦法: 1.強制選擇當前節點,用當前的狀態去更新子樹資訊,然後再用子樹資訊更新父親。 2
hdu-1561 The more, The Better (樹形dp入門,有依賴的揹包問題
The more, The Better Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4954
樹形依賴揹包
問題大意:給出一棵樹,根節點為1,每個點有毒素和收穫。要求毒素不超過給定值的情況下使收穫最大。一個點的父親節點被選取後這個點才能被選取。 首先弄出dfs序,也記錄下每個點其子樹及自身的大小。每個點都能夠被選或不選,如果選了才會考慮它子樹。 設f[i][j]表
BZOJ 1531: [POI2005]Bank notes 多重揹包
1531: [POI2005]Bank notes Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 506 Solved: 279 [Submit][
csu1580 樹形依賴揹包模板題
題意 有一輛能載客m的車,有n個人,然後第i個人上車的條件是第a[i]個人要上車,問最多能上幾個。 (題意很簡單吧。)。 思路 首先要明確一點,這些人的依賴可能會成環,也就是說一群人要一起
BZOJ 3163 Heoi2013 Eden的新揹包問題 多重揹包
題目大意:多重揹包,多次詢問某個物品不能選擇時以某個總價錢最多能獲得多少價值 求問正解是啥QAQ 維護一個字首多重揹包和一個字尾多重揹包 每次詢問時 列舉前面選多少和後面選多少 暴力統計答案即可 時間複雜度O(n^2logn+nq) 這3E的複雜度居然只跑了600sQAQ
HDU 1561 The more, The Better(多重揹包+樹形DP)
Problem Description ACboy很喜歡玩一種戰略遊戲,在一個地圖上,有N座城堡,每座城堡都有一定的寶物,在每次遊戲中ACboy允許攻克M個城堡並獲得裡面的寶物。但由於地理位置原因,有些城堡不能直接攻克,要攻克這些城堡必須先攻克其他某一個特定的城堡。你能幫A
BZOJ 4817: [Sdoi2017]樹點塗色
prepare new 來看 rep next 結果 wap tchar end 二次聯通門 : BZOJ 4817: [Sdoi2017]樹點塗色 /* BZOJ 4817: [Sdoi2017]樹點塗色 考場上打的暴力
bzoj 4819 [Sdoi2017]新生舞會
continue net map sizeof rip 還需 mes += scanf Description 學校組織了一次新生舞會,Cathy作為經驗豐富的老學姐,負責為同學們安排舞伴。有n個男生和n個女生參加舞會 買一個男生和一個女生一起跳舞,互為舞伴。Cathy收
BZOJ 4816: [Sdoi2017]數字表格
nbsp n) stream .com zoj www. pri oid [] 二次聯通門 : BZOJ 4816: [Sdoi2017]數字表格 /* BZOJ 4816: [Sdoi2017]數字表格 莫比烏斯反演 媽呀,我