[luoguP1272] 重建道路

传送门

奇奇怪怪的分组背包。

#include <cstdio>
#include <cstring>
#include <iostream>
#define N 151
#define min(x, y) ((x) < (y) ? (x) : (y))

int n, p, cnt, ans = ~(1 << 31);
int head[N], to[N], next[N], f[N][N];

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = -1;
	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - ‘0‘;
	return x * f;
}

inline void dfs(int u)
{
	int i, j, k, v;
	for(i = head[u]; i ^ -1; i = next[i])
	{
		v = to[i];
		dfs(v);
		for(j = p; j >= 1; j--)
			for(k = 1; k < j; k++)
				f[u][j] = min(f[u][j], f[u][j - k] + f[v][k] - 2);
	}
}

inline void add(int x, int y)
{
	to[cnt] = y;
	next[cnt] = head[x];
	head[x] = cnt++;
}

int main()
{
	int i, x, y;
	n = read();
	p = read();
	memset(f, 127 / 3, sizeof(f));
	memset(head, -1, sizeof(head));
	for(i = 1; i <= n; i++) f[i][0] = f[i][1] = 0;
	for(i = 1; i < n; i++)
	{
		x = read();
		y = read();
		add(x, y);
		f[x][1]++;
		f[y][1]++;
	}
	dfs(1);
	for(i = 1; i <= n; i++) ans = min(ans, f[i][p]);
	printf("%d\n", ans);
	return 0;
}

  

时间: 2025-01-01 11:30:02

[luoguP1272] 重建道路的相关文章

P1272 重建道路

P1272 重建道路 题目描述 一场可怕的地震后,人们用N个牲口棚(1≤N≤150,编号1..N)重建了农夫John的牧场.由于人们没有时间建设多余的道路,所以现在从一个牲口棚到另一个牲口棚的道路是惟一的.因此,牧场运输系统可以被构建成一棵树.John想要知道另一次地震会造成多严重的破坏.有些道路一旦被毁坏,就会使一棵含有P(1≤P≤N)个牲口棚的子树和剩余的牲口棚分离,John想知道这些道路的最小数目. 输入输出格式 输入格式: 第1行:2个整数,N和P 第2..N行:每行2个整数I和J,表示

P1272 重建道路(树形dp)

P1272 重建道路 题目描述 一场可怕的地震后,人们用N个牲口棚(1≤N≤150,编号1..N)重建了农夫John的牧场.由于人们没有时间建设多余的道路,所以现在从一个牲口棚到另一个牲口棚的道路是惟一的.因此,牧场运输系统可以被构建成一棵树.John想要知道另一次地震会造成多严重的破坏.有些道路一旦被毁坏,就会使一棵含有P(1≤P≤N)个牲口棚的子树和剩余的牲口棚分离,John想知道这些道路的最小数目. 输入输出格式 输入格式: 第1行:2个整数,N和P 第2..N行:每行2个整数I和J,表示

[Usaco2002 Feb]Rebuilding Roads重建道路

题目描述 一场可怕的地震后,奶牛用N个牲口棚(1 <= N <= 150,编号1..N)重建了农民John的牧场.奶牛没有时间建设多余的道路,所以现在从一个牲口棚到另一个牲口棚的道路是唯一的.因此,牧场运输系统可以被构建成一棵树.John想要知道另一次地震会造成多严重的破坏.有些道路一旦被毁坏,就会使一棵含有P(1 <= P <= N)个牲口棚的子树和剩余子牲口棚分离,John想知道这些道路的最小数目. 输入格式 第1行:2个整数, N和P 第2..N行:每行2个整数I和J,表示节

luogu P1272 重建道路

嘟嘟嘟 这好像是一种树上背包. 我们令dp[i][j] 表示在 i 所在的子树中(包括节点 i)分离出一个大小为 j 的子树最少需割多少条边. 那么转移方程就是 dp[u][j] = min(dp[u][j], dp[u][j - k] + dp[v][k] - 1) (v是u的一个儿子) 理解起来就是在u所在子树中切 j 个节点,等于在u中切 j - k 个节点加上在v所在子树中切 k 个节点所需要切的边数之和.又因为切出来的这两部分要合并得到一个节点数为 j 的,所以要减1. 1 #incl

重建道路

传送门 我们来看一道比较可做的树形DP. 现在这个数据规模的树形DP都是可以直接n3暴力转移过掉的呀-- 不过这个状态比较特殊,我们用dp[i][j]表示i节点在子树中保留j个节点所需要删去的最小边数. 那么转移方程就是,dp[i][j] = min(dp[i][j],dp[i][j-k] + dp[v][k] - 1);其中那个-1是节点i和节点v之间的连边,那个是要保留的orz,他之前会被重复计算. 所以我们直接这样暴力dp即可,一开始的初始化是dp[i][1] = son[i],son表示

9.12(多米诺骨牌+道路修建+重建道路)

一道dp: 有两个限制条件时可以考虑将其中一个存到维度,另外一个作为值,但一定要理清楚哪个是要优先满足的 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1002 4 int dp[N][10005],a[N],b[N],d[N]; 5 int main() 6 { 7 memset(dp,0x3f3f3f,sizeof(dp)); 8 int n; 9 scanf("%d",&n); 10

NYOJ 674 善良的国王(树形背包DP)

善良的国王 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 传说中有一个善良的国王Good,他为了不劳民伤财,每当建造一个城镇的时候都只用一条路去连接,这样就可以省很多的人力和物力,也就说如果有n个城镇,那么只需要n-1条路就可以把所有的城镇链接起来了(也就是一颗树了).但是不幸的事情发生了:有个一强大的帝国想要占领这个国家,但是由于国王Good的兵力不足,只能守护m个城镇,所以经过商量,国王Good只能从他的所有城镇中选择m个相链接的城市,并且把所有可以链接到这m

1002. [WZOI2011 S3] 周年纪念日

1002. [WZOI2011 S3] 周年纪念日 Problem 3 周年纪念日 (anniversary.pas/c/cpp) 背景 WZland即将迎来一个举国欢庆的日子—建国150亿周年纪念日,值此之际WZland有许多事情要准备…… 问题描述 WZland的国王决定举办一个晚会,这次晚会要求所有的WZland居民都参加,但是他发现WZland的所有城市之间的道路都已经毁坏(平时WZland的居民都在自己的城市里活动,所以他们对于那些道路一点都不关心).这是一件十分麻烦的事情,因为这个晚

几个树形dp

1.重建道路 树形dp基础题,f[i][j]表示在i这个点我和我的子树联通块大小为j最少砍几条边. 转移的时候,到下一个子树时上一个子树所有答案先++(此树直接砍掉不贡献答案),再继续dp. 注意更新答案时,如果不是跟答案还有+1(砍掉我和我父亲的),不然洛谷会挂四个点QAQ 马上就Noip了我还只能做这种水题QAQ 还挂 //Twenty #include<algorithm> #include<iostream> #include<cstring> #include