【BZOJ2427】[HAOI2010]軟件安裝 Tarjan+樹形背包
阿新 • • 發佈:2017-09-03
script sum 不能 成了 getch amp oid getc ron
5 5 6
2 3 4
0 1 1
【BZOJ2427】[HAOI2010]軟件安裝
Description
現在我們的手頭有N個軟件,對於一個軟件i,它要占用Wi的磁盤空間,它的價值為Vi。我們希望從中選擇一些軟件安裝到一臺磁盤容量為M計算機上,使得這些軟件的價值盡可能大(即Vi的和最大)。
但是現在有個問題:軟件之間存在依賴關系,即軟件i只有在安裝了軟件j(包括軟件j的直接或間接依賴)的情況下才能正確工作(軟件i依賴軟件j)。幸運的是,一個軟件最多依賴另外一個軟件。如果一個軟件不能正常工作,那麽它能夠發揮的作用為0。
我們現在知道了軟件之間的依賴關系:軟件i依賴軟件Di。現在請你設計出一種方案,安裝價值盡量大的軟件。一個軟件只能被安裝一次,如果一個軟件沒有依賴則Di =0,這時只要這個軟件安裝了,它就能正常工作。
Input
第1行:N, M (0<=N<=100, 0<=M<=500)
第2行:W1, W2, ... Wi, ..., Wn (0<=Wi<=M )
第3行:V1, V2, ..., Vi, ..., Vn (0<=Vi<=1000 )
第4行:D1, D2, ..., Di, ..., Dn (0<=Di<=N, Di≠i )
Output
一個整數,代表最大價值。
Sample Input
3 105 5 6
2 3 4
Sample Output
5題解:n個點n條邊,所以依賴關系一定會出現環,環中的要麽都取要麽都不取,那麽Tarjan縮環將環變成一個物品即可。然後原圖就變成了森林,新建0號點將所有樹根連起來然後跑樹形背包即可。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int n,m,tot,sum,top,cnt,ans; int w[110],v[110],d[110],dep[110],low[110],ins[110],sta[110],bel[110],W[110],V[110],D[110]; int to[110],next[110],head[110],f[110][510],vis[110]; inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘)f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } void tarjan(int x) { dep[x]=low[x]=++tot; ins[x]=1,sta[++top]=x; if(d[x]) { if(!dep[d[x]]) tarjan(d[x]),low[x]=min(low[x],low[d[x]]); else if(ins[d[x]]) low[x]=min(low[x],dep[d[x]]); } if(dep[x]==low[x]) { int t; sum++; do { t=sta[top--],bel[t]=sum,W[sum]+=w[t],V[sum]+=v[t],ins[t]=0; }while(t!=x); } } void add(int a,int b) { to[cnt]=b,next[cnt]=head[a],head[a]=cnt++; } void dfs(int x) { int i,j,k; for(i=0;i<W[x];i++) f[x][i]=-1<<29; f[x][W[x]]=V[x]; for(i=head[x];i!=-1;i=next[i]) { dfs(to[i]); for(j=m;j>=W[x]+W[to[i]];j--) for(k=W[to[i]];k<=j-W[x];k++) f[x][j]=max(f[x][j],f[x][j-k]+f[to[i]][k]); } } int main() { n=rd(),m=rd(); int i; for(i=1;i<=n;i++) w[i]=rd(); for(i=1;i<=n;i++) v[i]=rd(); for(i=1;i<=n;i++) d[i]=rd(); for(i=1;i<=n;i++) if(!dep[i]) tarjan(i); memset(head,-1,sizeof(head)); for(i=1;i<=n;i++) if(bel[d[i]]!=bel[i]) vis[bel[i]]=1,add(bel[d[i]],bel[i]); for(i=1;i<=sum;i++) if(!vis[i]) add(0,i); dfs(0); for(i=0;i<=m;i++) ans=max(ans,f[0][i]); printf("%d",ans); return 0; }
【BZOJ2427】[HAOI2010]軟件安裝 Tarjan+樹形背包