玄关求调 Tarjan + 树形 dp
查看原帖
玄关求调 Tarjan + 树形 dp
807826
zjpwdyf楼主2024/8/1 17:39

80 pts,WA on #5 #7

#include <bits/stdc++.h>
using namespace std;
const int N = 105, M = 505;
int n, m, w[N], v[N];
int tot, dfn[N], low[N], instk[N];
int sccid, scc[N], ww[N], vv[N];
int Link[N][N], din[N];
int dp[N][M];
stack <int> S;
vector <int> G[N], T[N];

void tarjan(int x) {
	dfn[x] = low[x] = ++tot;
	S.push(x);
	instk[x] = 1;
	for(int y : G[x]) {
		if(!dfn[y]) {
			tarjan(y);
			low[x] = min(low[x], low[y]);
		}
		else if(instk[y])
			low[x] = min(low[x], dfn[y]);
	}
	if(dfn[x] == low[x]) {
		sccid++;
		int tmp;
		do {
			tmp = S.top(); S.pop();
			instk[tmp] = 0;
			scc[tmp] = sccid;
			ww[sccid] += w[tmp];
			vv[sccid] += v[tmp];
		}
		while(tmp != x);
	}
}
void dfs(int x) {
	for(int y : T[x]) {
		dfs(y);
		for(int j = m; j; j--)
			for(int k = 1; k <= j - ww[x]; k++)
				dp[x][j] = max(dp[x][j], dp[y][k] + dp[x][j - k]);
	}
}
int main() {
	cin >> n >> m;
	for(int i = 1; i <= n; i++) cin >> w[i];
	for(int i = 1; i <= n; i++)	cin >> v[i];
	for(int i = 1; i <= n; i++) {
		int fa; cin >> fa;
		G[fa].push_back(i);
	}
	for(int i = 1; i <= n; i++)
		if(!dfn[i]) tarjan(i);
	for(int i = 1; i <= n; i++)
		for(int j : G[i])
			if(scc[i] != scc[j] && !Link[scc[i]][scc[j]]) {
				T[scc[i]].push_back(scc[j]);
				Link[scc[i]][scc[j]] = 1;
				din[scc[j]]++;
			}
	
	for(int i = 1; i <= sccid; i++) {
		if(!din[i]) T[0].push_back(i);
		dp[i][ww[i]] = vv[i];
	}
	dfs(0);
	int ans = 0;
	for(int i = 1; i <= m; i++)
		ans = max(ans, dp[0][i]);
	cout << ans;
	return 0;
}
2024/8/1 17:39
加载中...