P1272 重建道路

https://www.luogu.com.cn/problem/P1272

一个神奇的树形dp,大概就是下面这样转移的吧

dp[x][i]表示x为根,保留i个点最少删除几条边

#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 200+11;
const int INF = 1e7;


int dp[maxn][maxn];

vector<int>G[maxn];
void add(int x,int y){
	G[x].push_back(y);
}
int siz[maxn];
int list[maxn];

int dfs(int x,int fa){
	siz[x] =1;
	dp[x][1] = 0;
	
	for(int i=0;i<G[x].size();i++){
		int p = G[x][i];
		if(p == fa) continue;
		dfs(p,x);
		for(int i=1;i<=siz[x] + siz[p];i++)	{
			list[i] = dp[x][i];
			if(i > 1) dp[x][i] = INF;
		}
		
		for(int i=1;i<=siz[x];i++){
			for(int j=1;j<=siz[p];j++){
				
				dp[x][i+j] = min(list[i] + dp[p][j],min(dp[x][i+j],list[i+j] + 1));
				
				//               不删除当前边          删除当前边 
			}
		}
		//不删除当前边算贡
		siz[x] += siz[p];
		dp[x][1]++;
	}
	return 0;
}





int main(){
//	freopen("in.txt", "r", stdin);
//	freopen("out.txt", "w", stdout);


	int n,p;
	cin >> n >> p;
	
	for(int i=1;i<=n+10;i++){
		for(int j=2;j<=n+10;j++){
			dp[i][j] = INF;
		}
	}
	
	for(int i=1;i<n;i++){
		int x,y;
		cin>>x>>y;
		add(x,y);
		add(y,x);
	}
	
	dfs(1,-1);
	int ans = dp[1][p];
	
	for(int i=2;i<=n;i++){
		ans = min(ans,dp[i][p]+1);
	}
	
	cout<<ans<<endl;
	return 0;
}

  

寻找真正的热爱
原文地址:https://www.cnblogs.com/lesning/p/13866097.html