【HAOI2010】软件安装

题面

题解

缩点之后一个裸的树型背包

代码

#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;
}
posted @ 2019-01-04 16:24  xgzc  阅读(113)  评论(0编辑  收藏  举报