【题解】CF440D Berland Federalization

树形DP,

\(f_{u,i}\) 表示以 \(u\) 为根,取出 \(i\) 个节点子树的最少删边次数。

\[f_{u,i}=\min\{f_{u,i-k}+f_{v,k}\} \]

过程类似分组背包。特别地,当 \(k=0\)\(f_{u,i}\) 强制加 \(1\)

但题目要输出方案怎么办呢?可以用 \(g_{u,i}\) 记录一下 \(f_{u,i}\) 的后继状态,转移时从 \(g_{u,i-k}\) 复制。后继状态中显然当 \(i=0\)\(u\) 要被删去。

复制后继状态看似给复杂度加了一维,但由于复制时间只与该点的子节点数决定,而子节点数是均摊的,所以不会超时。

注意,当根节点不为 \(1\) 时 ans++。

Code:

#include <bits/stdc++.h>
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
using namespace std;

const int maxn=405;
int n,k;
int id[maxn][maxn];
vector<pii> g[maxn][maxn];

struct node{
	int v,nxt;
}edge[maxn*2];int head[maxn],cntE;


void add(int u,int v){
	edge[++cntE]=(node){v,head[u]};
	head[u]=cntE;
}

int sz[maxn],fa[maxn];
int f[maxn][maxn];

void cpy(int u,int j,int t){
	g[u][j].clear();
	for(int i=0;i<g[u][t].size();i++){
		g[u][j].pb(g[u][t][i]);
	}
}

void init(int u,int p){
	sz[u]=1;
	fa[u]=p;
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].v;
		if(v==p) continue;
		init(v,u);
		sz[u]+=sz[v];
	}
}

void dfs(int u,int p){
	f[u][1]=f[u][sz[u]]=0;
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].v;
		if(v==p) continue;
		dfs(v,u);
		for(int j=sz[u];j>=0;j--){
			for(int k=0;k<=min(sz[v],j);k++){
				if(!k){
					f[u][j]++;
					g[u][j].pb(mp(v,0));
				}
				else
				if(f[u][j-k]+f[v][k]<f[u][j]){
					f[u][j]=f[u][j-k]+f[v][k];
					cpy(u,j,j-k);
					g[u][j].pb(mp(v,k));
				}
			}
		}
	}
}

void get_ans(int u,int w){
	for(int i=0;i<g[u][w].size();i++){
		if(g[u][w][i].second==0){
			if(g[u][w][i].first!=1) printf("%d ",id[u][g[u][w][i].first]);
		}else get_ans(g[u][w][i].first,g[u][w][i].second);
	}
}

int main(){
	scanf("%d%d",&n,&k);
	memset(f,0x3f,sizeof f);
	for(int i=1;i<=n-1;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		id[u][v]=id[v][u]=i;
		add(u,v);add(v,u);
	}
	init(1,1);
	dfs(1,1);
	int ans=f[1][k],rt=1;
	for(int u=2;u<=n;u++){
		if(k>sz[u]) continue;
		if(f[u][k]+1<ans){
			ans=f[u][k]+1;
			rt=u;
		}
	}
	printf("%d\n",ans);
	if(rt!=1){
		printf("%d ",id[fa[rt]][rt]);
	}
	if(k!=sz[rt])
	get_ans(rt,k);
}
posted @ 2022-01-02 19:10  HyperSQ  阅读(29)  评论(0)    收藏  举报