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 )

 

输出格式:

 

一个整数,代表最大价值

 

输入输出样例

输入样例#1: 复制
3 10
5 5 6
2 3 4
0 1 1
输出样例#1: 复制
5

 

分析

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 }

 

posted @ 2017-11-26 14:15  MJT12044  阅读(251)  评论(0编辑  收藏  举报