Testing Round #10 D. Berland Federalization 树形DP

版权声明:xgc原创文章,未经允许不得转载。 https://blog.csdn.net/xgc_woker/article/details/82907365

Description
给你一棵树,最少的删掉哪些边能使得余下的至少有1个大小刚好为k的残树给出方案。


Sample Input
5 2
1 2
2 3
3 4
4 5


Sample Output
1
2


来填坑啦。。。
直接树形DP,设f[i][k]为第i个点为根,形成k大小的树的最小值。
输出方案用vector即可。


#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long LL;
int _min(int x, int y) {return x < y ? x : y;}
int _max(int x, int y) {return x > y ? x : y;}
int read() {
	int s = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
	return s * f;
}

struct edge {
	int x, y, next;
} e[810]; int len, last[410];
int K, tot[410], f[410][410], tf[410], ll[410];
vector<int> v[410][410], p[410];

void ins(int x, int y) {
	e[++len].x = x, e[len].y = y;
	e[len].next = last[x], last[x] = len;
}

void treedp(int x, int fa) {
	tot[x] = 1; f[x][1] = 0;
	for(int k = last[x]; k; k = e[k].next) {
		int y = e[k].y;
		if(y != fa) {
			ll[y] = k / 2;
			treedp(y, x);
			memset(tf, 63, sizeof(tf));
			for(int i = tot[x]; i >= 1; i--) {
				if(tf[i] > f[x][i] + 1) {
					tf[i] = f[x][i] + 1;
					p[i] = v[x][i];
					p[i].push_back(k / 2);
				}
			}
			for(int i = 1; i <= tot[x]; i++) {
				for(int j = 1; j <= tot[y]; j++) {
					if(i + j > K) break;
					if(tf[i + j] > f[x][i] + f[y][j]) {
						tf[i + j] = f[x][i] + f[y][j];
						p[i + j] = v[x][i];
						for(int q = 0; q < v[y][j].size(); q++) p[i + j].push_back(v[y][j][q]);
					}
				}
			} tot[x] += tot[y];
			for(int i = 0; i <= tot[x]; i++) f[x][i] = tf[i], v[x][i] = p[i], p[i].clear();
		}
	} f[x][tot[x]] = 0;
}

int main() {
	int n = read(); K = read(); len = 1;
	for(int i = 1; i < n; i++) {
		int x = read(), y = read();
		ins(x, y), ins(y, x);
	} memset(f, 63, sizeof(f));
	treedp(1, 0);
	int ans = f[1][K], pos = 1;
	for(int i = 2; i <= n; i++) {
		if(f[i][K] + 1 < ans) ans = f[i][K] + 1, pos = i;
	}
	printf("%d\n", ans);
	if(pos != 1) v[pos][K].push_back(ll[pos]);
	for(int i = 0; i < v[pos][K].size(); i++) printf("%d ", v[pos][K][i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/xgc_woker/article/details/82907365