【HAOI2010】軟體安裝
阿新 • • 發佈:2019-01-04
題面
題解
縮點之後一個裸的樹型揹包
程式碼
#include<cstdio> #include<cstring> #include<algorithm> #define RG register #define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout); using std::min; using std::max; inline int read() { int data = 0, w = 1; char ch = getchar(); while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if(ch == '-') w = -1, ch = getchar(); while(ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar(); return data * w; } const int maxn(1010); struct edge { int next, to; } e[maxn << 1]; int n, m, e_num, top, col, cnt, W[maxn], w[maxn], V[maxn], v[maxn], f[maxn][maxn], head[maxn]; inline void add_edge(int from, int to) { e[++e_num] = (edge) {head[from], to}; head[from] = e_num; } int dfn[maxn], low[maxn], stk[maxn], belong[maxn], d[maxn], ind[maxn]; void Tarjan(int x) { dfn[x] = low[x] = ++cnt; stk[++top] = x; for(RG int i = head[x]; i; i = e[i].next) { int to = e[i].to; if(!dfn[to]) Tarjan(to), low[x] = min(low[x], low[to]); else if(!belong[to]) low[x] = min(low[x], dfn[to]); } if(dfn[x] == low[x]) { belong[x] = ++col; V[col] = v[x]; W[col] = w[x]; while(stk[top] != x) belong[stk[top]] = col, V[col] += v[stk[top]], W[col] += w[stk[top--]]; --top; } } void dfs(int x) { for(RG int i = W[x]; i <= m; i++) f[x][i] = V[x]; for(RG int i = head[x]; i; i = e[i].next) { int to = e[i].to; dfs(to); for(RG int j = m - W[x]; j >= 0; j--) for(RG int k = 0; k <= j; k++) f[x][j + W[x]] = max(f[x][j + W[x]], f[to][k] + f[x][j + W[x] - k]); } } int main() { scanf("%d%d", &n, &m); for(RG int i = 1; i <= n; i++) scanf("%d", w + i); for(RG int i = 1; i <= n; i++) scanf("%d", v + i); for(RG int i = 1; i <= n; i++) { scanf("%d", d + i); if(d[i]) add_edge(d[i], i); } for(RG int i = 1; i <= n; i++) if(!dfn[i]) Tarjan(i); memset(head, 0, sizeof(head)); memset(e, 0, sizeof(e)); e_num = 0; for(RG int i = 1; i <= n; i++) if(belong[d[i]] != belong[i]) add_edge(belong[d[i]], belong[i]), ++ind[belong[i]]; for(RG int i = 1; i <= col; i++) if(ind[i] == 0) add_edge(0, i); dfs(0); printf("%d\n", f[0][m]); return 0; }