[填坑][支線任務]樹形DP 樹形背包
阿新 • • 發佈:2017-10-28
adc update next 分組背包 背包問題 == fine long bzoj
開啟了樹包支線任務QAQ
我還是弱啊==
[樹形背包]BZOJ 2427 軟件安裝
這道題原來考過,大概是半年前了,然而現在再回來填坑,卻發現還是會的不透徹,頹了頹原來自己的代碼T-T
這就是有依賴的背包問題,可以看做分組背包,但是會有很多冗雜的狀態,所以我們要對依賴它的“附件”進行一次01背包,把它們泛化
然後我們要把“主件”選上(因為必須要有它),和泛化後的“附件”新組合成物品。當然它也可以單獨存在,不選任何“附件”。
當然這道題有坑點:可能有依賴環出現,所以我們要Tarjan縮一下點(最開始一直WA竟然是因為Tarjan打錯了,悲傷==)
update:因為是一片森林,所以我們要建一個超級源點233
#include<iostream> #include<cstdio> #include<cstdio> #define pos(i,a,b) for(int i=(a);i<=(b);i++) #define pos2(i,a,b) for(int i=(a);i>=(b);i--) #define N 2011 #define LL long long using namespace std; struct haha{ int next,to; }edge[N*10],edgechu[N*10]; int head[N],cnt=1,headchu[N],cntchu=1; void add(int u,int v){ edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; } void addchu(int u,int v){ edgechu[cntchu].to=v; edgechu[cntchu].next=headchu[u]; headchu[u]=cntchu++; } int n,m,in[N],wchu[N],vchu[N]; int dfn[N],ji,low[N],hea,instack[N],stack[N]; int cntt,v[N],w[N],belong[N]; void tarjan(int x){ dfn[x]=low[x]=++ji; instack[x]=1;stack[++hea]=x; for(int i=headchu[x];i;i=edgechu[i].next){ int to=edgechu[i].to; if(dfn[to]==-1){ tarjan(to); low[x]=min(low[x],low[to]); } else if(instack[to]) low[x]=min(low[x],dfn[to]); } if(low[x]==dfn[x]){ int temp; cntt++; while(1){ temp=stack[hea--]; instack[temp]=0; w[cntt]+=wchu[temp]; v[cntt]+=vchu[temp]; belong[temp]=cntt; if(temp==x) break; } } } int f[N][N],root,out[N]; void dfs(int x){ if(out[x]==0){ pos2(i,m,w[x]) f[x][i]=v[x]; return; } for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; dfs(to); } for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; pos2(j,m,0){ pos2(k,j,0){ f[x][j]=max(f[x][j],f[x][j-k]+f[to][k]); } } } pos2(i,m,0){ if(i>=w[x]) f[x][i]=f[x][i-w[x]]+v[x]; else f[x][i]=0; } } int main(){ scanf("%d%d",&n,&m); pos(i,1,n) scanf("%d",&wchu[i]); pos(i,1,n) scanf("%d",&vchu[i]); pos(i,1,n){ int x;scanf("%d",&x); if(x) addchu(x,i); } pos(i,0,n) dfn[i]=-1; pos(i,1,n) if(dfn[i]==-1) tarjan(i); pos(x,1,n){ for(int i=headchu[x];i;i=edgechu[i].next){ int to=edgechu[i].to; if(belong[to]!=belong[x]){ add(belong[x],belong[to]);out[belong[x]]++;in[belong[to]]++; } } } root=0; pos(i,1,cntt){ if(in[i]==0){ add(root,i);out[root]++; } } dfs(root); cout<<f[root][m]; return 0; }
[填坑][支線任務]樹形DP 樹形背包