洛谷 P2515 [HAOI2010]软件安装
题目描述
现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi。我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大)。
但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。
我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。
输入输出格式
输入格式:
第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 )
输出格式:
一个整数,代表最大价值
输入输出样例
输入样例#1:
3 10
5 5 6
2 3 4
0 1 1
输出样例#1:
5
思路:tarjin缩点+树形DP
错因:MLE
#include<map> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 10001 #define M 2501 using namespace std; map<int,int>ma[N]; int n,m,K; int tot,top; int tim,sum,sumcol; int col[N],kk[N],vval[N]; int to[N],net[N],head[N]; int k[N],val[N],f[N][M],dp[M]; int dad[N],lchild[N],rchild[N]; int vis[N],dis[N],low[N],stack[N],visstack[N]; void add(int u,int v){ to[++tot]=v;net[tot]=head[u];head[u]=tot; } void tarjin(int now){ dis[now]=low[now]=++tim; vis[now]=1; stack[++top]=now; visstack[now]=1; for(int i=head[now];i;i=net[i]) if(visstack[to[i]]) low[now]=min(low[now],dis[to[i]]); else if(!vis[to[i]]){ tarjin(to[i]); low[now]=min(low[now],low[to[i]]); } if(low[now]==dis[now]){ sumcol++; col[now]=sumcol; while(stack[top]!=now){ col[stack[top]]=sumcol; visstack[stack[top]]=0; top--; } visstack[now]=0; top--; } } int dfs(int i,int j){ if(i>n||i<1||j>K||j<1) return 0; if(f[i][j]) return f[i][j]; for(int kkk=0;kkk<=j-kk[i];kkk++) f[i][j]=max(f[i][j],dfs(lchild[i],kkk)+dfs(rchild[i],j-kkk-kk[i])+vval[i]); f[i][j]=max(f[i][j],dfs(rchild[i],j)); return f[i][j]; } int main(){ scanf("%d%d",&n,&K); for(int i=1;i<=n;i++) scanf("%d",&k[i]); for(int i=1;i<=n;i++) scanf("%d",&val[i]); for(int i=1;i<=n;i++){ int x; scanf("%d",&x); if(x!=0) add(x,i); } for(int i=1;i<=n;i++) if(!vis[i]) tarjin(i); for(int i=1;i<=n;i++) for(int j=head[i];j;j=net[j]) if(col[i]!=col[to[j]]) if(ma[col[i]].find(col[to[j]])==ma[col[i]].end()){ ma[col[i]][col[to[j]]]=1; dad[col[to[j]]]=col[i]; } for(int i=1;i<=sumcol;i++){ int fa=dad[i]; if(!lchild[fa]) lchild[fa]=i; else{ fa=lchild[fa]; while(rchild[fa]) fa=rchild[fa]; rchild[fa]=i; } } for(int i=1;i<=n;i++){ kk[col[i]]+=k[i]; vval[col[i]]+=val[i]; } cout<<dfs(lchild[0],K); }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。