×

第三篇:P1272

题解补完计划:第三篇

原题题面

显然,题目是一棵树,考虑 DP,令 \(dp_{i, j}\) 表示在子树 \(i\) 内,留下 \(j\) 大小的且包含 \(i\) 的联通块的最小代价。

转移有:
\(ndp_{u, i+j} = min_{i=1}^{sz_u} min_{i=1}^{sz_v} dp_{u, i} + dp_{v, j}\)。
表示同时包含 \(u, v\) 的情况下的最小代价。
\(ndp_{u, i} = min(ndp_{u,i}, dp_{u, i}+1)\)。
表示不包含 \(v\) 时的最小代价。

代码:

#include<bits/stdc++.h>
using namespace std;
#define N 205
#define intl long long
#define inf (0x3f3f3f3f3f3f3f3f)
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
	intl x=0,k=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
	while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*k;
}
intl dp[N][N], sz[N], n, p, tmp[N]; 
vector<intl> g[N];
void dfs(intl u) {
	sz[u] = 1;dp[u][1] = 0;
	for(auto v:g[u]) {
		dfs(v);
		For(i,0,sz[u] + sz[v]) tmp[i] = inf;
		For(i,1,sz[u]) For(j,1,sz[v]) tmp[i+j] = min(tmp[i+j], dp[u][i] + dp[v][j]);
		For(i,0,sz[u]) tmp[i] = min(tmp[i], dp[u][i] + 1);
		sz[u] += sz[v];
		For(i,0,sz[u]) dp[u][i] = tmp[i];
	}
	dp[u][sz[u]] = 0;
}
int main() {
	n = read(), p = read();
	For(i,2,n) {
		intl u = read(), v = read();
		g[u].push_back(v);
	}
	For(i,0,n) For(j,0,n) dp[i][j] = inf;
	dfs(1);
	intl ans = inf;
	For(i,1,n) {
		if(dp[i][p] == inf) continue;
		ans = min(ans, dp[i][p] + (i != 1));
	}
	printf("%lld\n", ans);
	return 0;
}


posted @ 2026-10-05 17:22  shiori123  阅读(2)  评论(0)    收藏  举报