P2515 [HAOI2010]软件安装
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 )
输出格式:
一个整数,代表最大价值
输入输出样例
分析
tarjan缩点+树形背包(好难调试啊啊)
code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 #include<vector> 7 #include<iostream> 8 9 using namespace std; 10 11 const int N = 210; 12 const int M = 510; 13 struct Edge{ 14 int to,nxt; 15 }e[M]; 16 int head[N],dfn[N],low[N],st[N],bel[N]; 17 int w[N],W[N],v[N],V[N],dp[N][M],ru[N]; 18 bool vis[N]; 19 int cnt,tn,tot,top,n,m; 20 vector<int>s[N]; 21 22 inline char nc() { 23 static char buf[100000],*p1 = buf,*p2 = buf; 24 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++; 25 } 26 inline int read() { 27 int x = 0,f = 1;char ch = nc(); 28 for (; ch<'0'||ch>'9'; ch = nc()) 29 if (ch=='-') f = -1; 30 for (; ch>='0'&&ch<='9'; ch = nc()) 31 x = x*10+ch-'0'; 32 return x * f; 33 } 34 35 inline void add_edge(int u,int v) { 36 e[++tot].to = v,e[tot].nxt = head[u],head[u] = tot; 37 } 38 39 void tarjan(int u) { 40 dfn[u] = low[u] = ++tn; 41 st[++top] = u; 42 vis[u] = true; 43 for (int i=head[u]; i; i=e[i].nxt) { 44 int v = e[i].to; 45 if (!dfn[v]) { 46 tarjan(v); 47 low[u] = min(low[u],low[v]); 48 } 49 else if (vis[v]) 50 low[u] = min(low[u],dfn[v]); 51 } 52 if (low[u]==dfn[u]) { 53 ++cnt; 54 do { 55 vis[st[top]] = false; 56 bel[st[top]] = cnt; 57 W[cnt] += w[st[top]]; 58 V[cnt] += v[st[top]]; 59 top--; 60 } while (st[top+1] != u); 61 } 62 } 63 void dfs(int u) { 64 for (int i=V[u]; i<=m; ++i) dp[u][i] = W[u]; 65 int tmp = s[u].size(); 66 for (int i=0; i<tmp; ++i) { 67 int v = s[u][i]; 68 dfs(v); 69 for (int j=m; j>=V[u]; --j) 70 for (int k=0; k<=j-V[u]; ++k) 71 dp[u][j] = max(dp[u][j],dp[v][k]+dp[u][j-k]); 72 } 73 } 74 75 int main() { 76 77 n = read(),m = read(); 78 for (int i=1; i<=n; ++i) v[i] = read(); 79 for (int i=1; i<=n; ++i) w[i] = read(); 80 for (int x,i=1; i<=n; ++i) { 81 x = read();if (x) add_edge(x,i); 82 } 83 for (int i=1; i<=n; ++i) 84 if (!dfn[i]) tarjan(i); 85 86 for (int i=1; i<=n; ++i) 87 for (int j=head[i]; j; j=e[j].nxt) { 88 if (bel[i] != bel[e[j].to]) { 89 s[bel[i]].push_back(bel[e[j].to]); 90 ru[bel[e[j].to]]++; 91 } 92 } 93 for (int i=1; i<=cnt; ++i) 94 if (!ru[i]) s[0].push_back(i); 95 dfs(0); 96 printf("%d",dp[0][m]); 97 return 0; 98 }