[Codeforces 440D]Berland Federalization

题目大意:给你一棵n个节点的树,现在要你删除尽可能少的边,使得剩余一个节点数刚好为k的子树。你需要输出节点数和删除的边的编号。

解题思路:树形dp。

设dp[i][j]和v[i][j]表示以i为根的子树中删除j个节点最少删的边数,和其所需删除的边对应的(点,删除的节点个数),用一个pair存储。

那么转移状态的时候类似于背包问题。

dp[i][j]=min{dp[s][k]+dp[i][j-k]}(s为i的儿子)。

更新答案的同时暴力更新v即可。

最后搜索根,注意如果根不为1,则需要把根与它的父亲的连边也去掉,即答案要+1。

时间复杂度$O(n^3)$。

C++ Code:

#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#define N 405
using namespace std;
vector<pair<int,int> >v[N][N],G[N];
int n,k,fa[N],sz[N],dp[N][N];
inline int readint(){
	char c=getchar();
	for(;!isdigit(c);c=getchar());
	int d=0;
	for(;isdigit(c);c=getchar())
	d=(d<<3)+(d<<1)+(c^‘0‘);
	return d;
}
void dfs(int now,int pre){
	sz[now]=1;
	for(int i=0,s=G[now].size();i<s;++i){
		int to=G[now][i].first;
		if(to!=pre){
			dfs(to,now);
			fa[to]=G[now][i].second;
			sz[now]+=sz[to];
		}
	}
}
void dfs2(int now,int pre){
	if(now==1)dp[now][sz[now]]=0;else{
		dp[now][sz[now]]=1;
		v[now][sz[now]].clear();
		v[now][sz[now]].push_back(make_pair(now,sz[now]));
	}
	dp[now][0]=0;
	for(int i=0,s=G[now].size();i<s;++i){
		int to=G[now][i].first;
		if(to!=pre){
			dfs2(to,now);
			for(int j=sz[now];j;--j)
			for(int k=0;k<=sz[to]&&k<=j;++k)
			if(dp[now][j]>dp[to][k]+dp[now][j-k]){
				dp[now][j]=dp[to][k]+dp[now][j-k];
				v[now][j]=v[now][j-k];
				v[now][j].push_back(make_pair(to,k));
			}
		}
	}
}
void print(int now,int p){
	if(sz[now]==p){
		printf("%d ",fa[now]);
		return;
	}
	for(int i=0,s=v[now][p].size();i<s;++i)
	print(v[now][p][i].first,v[now][p][i].second);
}
int main(){
	n=readint(),k=readint();
	for(int i=1;i<n;++i){
		int x=readint(),y=readint();
		G[x].push_back(make_pair(y,i));
		G[y].push_back(make_pair(x,i));
	}
	memset(dp,0x3f,sizeof dp);
	fa[1]=0;
	dfs(1,0);
	dfs2(1,0);
	int ans=dp[1][n-k],rt=1;
	for(int i=2;i<=n;++i)
	if(sz[i]>=k&&dp[i][sz[i]-k]+1<ans){
		ans=dp[i][sz[i]-k]+1;
		rt=i;
	}
	printf("%d\n",ans);
	if(rt!=1)printf("%d ",fa[rt]);
	print(rt,sz[rt]-k);
	return 0;
}

原文地址:https://www.cnblogs.com/Mrsrz/p/8157891.html

时间: 2024-08-06 14:21:07

[Codeforces 440D]Berland Federalization的相关文章

CodeForces 567B Berland National Library

Description Berland National Library has recently been built in the capital of Berland. In addition, in the library you can take any of the collected works of Berland leaders, the library has a reading room. Today was the pilot launch of an automated

CodeForces 567B Berland National Library(模拟)(简单)

B. Berland National Library time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Berland National Library has recently been built in the capital of Berland. In addition, in the library you can t

CodeForces - 1073D Berland Fair

XXI Berland Annual Fair is coming really soon! Traditionally fair consists of nnbooths, arranged in a circle. The booths are numbered 11 through nn clockwise with nnbeing adjacent to 11. The ii-th booths sells some candies for the price of aiai burle

CodeForces 567B Berland National Library hdu

这类题一个操作增加多少,一个操作减少多少,求最少刚开始为多少,在中途不会出现负值,模拟一遍,用一个数记下最大的即可 1 #include<cstdio> 2 #include<cstring> 3 4 const int HASH=57; 5 6 int n,num[110],head[HASH],next[110]; 7 8 void insert(int s) 9 { 10 int h=num[s]%HASH; 11 int u=head[h]; 12 while(u) u=n

Codeforces 1005F Berland and the Shortest Paths 【最短路树】【性质】

其实是一道裸题,如果没学过最短路树的话会比较难做,要想很久想到关键性质才能做出来. 最短路树顾名思义,就是从一个图中生成出来一棵树,使得每个顶点到root的距离是单源最短路.如果有这样的树的话,那可见这样的树是符合题意的. 怎么生成这样的树呢?关键在于记录前驱father,一个距离root最短路是6的点必定从一个距离root最短路是5的点到达(这两个点之间一定会有一条边).所以我们对于所有顶点 2-n,每个顶点u我们找dis[u] = dis[v]+1的情况,这样的话v就是u的前驱.若v,u之间

2018省赛赛第一次训练题解和ac代码

第一次就去拉了点思维很神奇的CF题目 # Origin Title     A CodeForces 607A Chain Reaction     B CodeForces 385C Bear and Prime Numbers     C CodeForces 670D2 Magic Powder - 2     D CodeForces 360B Levko and Array     E CodeForces 68B Energy exchange     F CodeForces 24

2018SDIBT_国庆个人第三场

A - A CodeForces - 1042A There are nn benches in the Berland Central park. It is known that aiai people are currently sitting on the ii-th bench. Another mm people are coming to the park and each of them is going to have a seat on some bench out of n

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

题目链接:Educational Codeforces Round 21 G. Anthem of Berland 题意: 给你两个字符串,第一个字符串包含问号,问号可以变成任意字符串. 问你第一个字符串最多包含多少个第二个字符串. 题解: 考虑dp[i][j],表示当前考虑到第一个串的第i位,已经匹配到第二个字符串的第j位. 这样的话复杂度为26*n*m*O(fail). fail可以用kmp进行预处理,将26个字母全部处理出来,这样复杂度就变成了26*n*m. 状态转移看代码(就是一个kmp

Codeforces Round #375 (Div. 2) D. Lakes in Berland DFS

D. Lakes in Berland 链接: http://codeforces.com/problemset/problem/723/D 题意 给你一个n/*m的矩阵,然后你们有不少于k条湖泊,然后你需要使得一些湖泊变成陆地,使得湖泊的数量恰好等于k,问你至少填多少个水. 湖泊不与外界相邻. 题解: 直接dfs搜出每一条湖泊,然后放在优先队列里,从小到大去填满就好了. 代码: 1 #include<iostream> 2 #include<queue> 3 #include&l