洛谷 P2515 軟件安裝 —— tarjan + 樹形揹包

題目鏈接:點我啊╭(╯^╰)╮

題目大意:

    每個點有重量、價值、依賴點
    樹形揹包模型,求體積爲 MM 的揹包的最大值

解題思路:

    注意根據依賴點建圖後不是樹和森林
    因爲會形成環,環上的點要麼都選,要麼都不選
    因此 tarjantarjan 縮點後跑一下樹形揹包即可
    這裏用了 dfsdfs 序的 O(nw)O(nw) 算法
    namonamo 爲什麼 P2014 [CTSC1997]選課 這道題就是森林而不會形成環呢?
    注意數組越界報wa會多折騰幾個小時

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 2e3 + 5;
int n, m, d[maxn], w[maxn], v[maxn]; 
int nw[maxn], nv[maxn], nw2[maxn], nv2[maxn];
int dfn[maxn], low[maxn], vis[maxn], col[maxn];
int s[maxn], top, tot, numc, nxt[maxn];
int dp[maxn][505], in[maxn];
vector <int> g[maxn];

void tarjan(int u){
	dfn[u] = low[u] = ++tot;
	s[++top] = u;
	vis[u] = 1;
	for(auto v : g[u]){
		if(!dfn[v]){
			tarjan(v);
			low[u] = min(low[u], low[v]);
		} else if(vis[v]) low[u] = min(low[u], dfn[v]);
	}
	if(dfn[u] == low[u]){
		++numc;
		while(s[top+1] ^ u){
			col[s[top]] = numc;
			nw[numc] += w[s[top]]; 
			nv[numc] += v[s[top]]; 
			vis[s[top--]] = 0;
		}
	}
}

void dfs(int u){
	dfn[u] = tot++;
	for(auto v : g[u]) dfs(v);
	nxt[dfn[u]] = tot;
}

signed main() {
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++) scanf("%d", w+i);
	for(int i=1; i<=n; i++) scanf("%d", v+i);
	for(int i=1; i<=n; i++) {
		scanf("%d", d+i);
		if(d[i]) g[d[i]].push_back(i);
	}
	for(int i=1; i<=n; i++)
		if(!dfn[i]) tarjan(i);
		
	for(int i=0; i<=n; i++) g[i].clear();
	for(int i=1; i<=n; i++)
		if(col[i] ^ col[d[i]] && d[i]) 
			g[col[d[i]]].push_back(col[i]), in[col[i]]++;
	for(int i=1; i<=numc; i++)
		if(!in[i]) g[0].push_back(i);
		
	dfs(tot = 0);
	memset(dp, 128, sizeof(dp));
	memset(dp[0], 0, sizeof(dp[0]));
	for(int i=1; i<=numc; i++) nw2[dfn[i]] = nw[i];
	for(int i=1; i<=numc; i++) nv2[dfn[i]] = nv[i];
	for(int i=0; i<=numc; i++)
		for(int j=0; j<=m; j++){
			dp[nxt[i]][j] = max(dp[nxt[i]][j], dp[i][j]);
			if(j + nw2[i] > m) continue; 
			dp[i+1][j+nw2[i]] = max(dp[i+1][j+nw2[i]], dp[i][j] + nv2[i]);
		}
	printf("%d\n", dp[numc+1][m]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章