2020(ICPC)亞洲區域賽(南京) M.Monster Hunter


2020(ICPC)亞洲區域賽(南京) M.Monster Hunter

題意

給定一顆大小為\(n\)的有根樹,每個結點都有點權\(hp[i]\),選取點的代價是\(hp[i] + \sum_{son of i} hp[j]\),且其父親也被選

現在可以在這棵樹中刪除\(0-n\)個點,問刪除這些點的情況下最小的代價分別是多少

\[2 \leq n \leq 2\times 10^3\\ 1\leq hp\leq 10^9 \]

分析

樹上背包問題

\(f[i][j][k]\)表示以\(i\)為根的子樹,\(i\)是否選取,子樹中一共選取\(j\)個點的情況下的最小代價是多少

轉移方程

\[f[x][j + k][1] = min(f[x][j][1]+min(f[v][k][0],f[v][k][1]+hp[v]))\\ f[x][j + k][0] = min(f[x][j][0] + min(f[v][k][0],f[v][k][1])) \]

復雜度的正確性在於任意兩點只被枚舉到一次,因此復雜度\(O(n^2)\)

代碼

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;

ll rd(){
	ll x = 0;
	int f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9'){
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9'){
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
} 

const int maxn = 4005;

int n,m;
ll p[maxn],hp[maxn];
vector<int> e[maxn];
ll f[maxn][maxn][2];

int siz[maxn];

void dfs(int x){
	f[x][0][0] = 0;
	f[x][1][1] = hp[x];
	siz[x] = 1;
	for(auto v:e[x]){
		dfs(v);
		for(int j = siz[x];j >= 0;j--){
			for(int k = siz[v];k >= 0;k--){
				f[x][j + k][1] = min(f[x][j + k][1],f[x][j][1] + min(f[v][k][0],f[v][k][1] + hp[v]));
				f[x][j + k][0] = min(f[x][j + k][0],f[x][j][0] + min(f[v][k][0],f[v][k][1]));
			}
		}
		siz[x] += siz[v];
	}
}

void solve(){
	int n = rd();
	for(int i = 1;i <= n;i++) e[i].clear();
	for(int i = 1;i <= n;i++)
		for(int j = 0;j <= n;j++)
			f[i][j][0] = f[i][j][1] = 1e18 + 7;
	for(int i = 2;i <= n;i++){
		p[i] = rd();
		e[p[i]].pb(i);
	}
	for(int i = 1;i <= n;i++)
		hp[i] = rd();
	dfs(1);
	for(int i = n;i >= 0;i--)
		printf("%lld ",min(f[1][i][0],f[1][i][1]));
	puts("");
}


int main(){
	int T = rd();
	while(T--)
		solve();
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM