【树形dp】Rebuilding Roads

[POJ1947]Rebuilding Roads

Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 11934   Accepted: 5519

Description

The cows have reconstructed Farmer John‘s farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The cows didn‘t have time to rebuild any extra roads, so now there is exactly one way to get from any given barn to any other barn. Thus, the farm transportation system can be represented as a tree.

Farmer John wants to know how much damage another earthquake could do. He wants to know the minimum number of roads whose destruction would isolate a subtree of exactly P (1 <= P <= N) barns from the rest of the barns.

Input

* Line 1: Two integers, N and P

* Lines 2..N: N-1 lines, each with two integers I and J. Node I is node J‘s parent in the tree of roads.

Output

A single line containing the integer that is the minimum number of roads that need to be destroyed for a subtree of P nodes to be isolated.

Sample Input

11 6
1 2
1 3
1 4
1 5
2 6
2 7
2 8
4 9
4 10
4 11

Sample Output

2

Hint

[A subtree with nodes (1, 2, 3, 6, 7, 8) will become isolated if roads 1-4 and 1-5 are destroyed.]

Source

USACO 2002 February

题目大意:有一颗N个节点的树,问最少删去几条边使剩下的树的大小有一颗为P?

直接写不就好了么?

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;

inline int read(){
	int x=0,f=1;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
	for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
	return x*f;
}
const int MAXN=100001;
const int INF=999999;
int N,M;
vector<int> vec[201];
int dp[201][201];
int ans=INF;

void dfs(int x,int fa){
	int cnt=0;
	for(int i=0;i<vec[x].size();i++){
		if(vec[x][i]!=fa)
			dfs(vec[x][i],x),cnt++;
	}
	dp[x][1]=dp[x][0]=0;
	for(int i=0;i<vec[x].size();i++){
		if(vec[x][i]!=fa)
		for(int j=M;j>=1;j--){
			if(dp[x][j]!=INF) dp[x][j]++;
			for(int k=1;k<=M;k++){
			    if(k>=j||dp[vec[x][i]][k]==INF) break;
			    if(dp[x][j-k]!=INF) dp[x][j]=min(dp[vec[x][i]][k]+dp[x][j-k],dp[x][j]);
			}
		}
	}
	if(x!=1) ans=min(ans,dp[x][M]+1);
	else ans=min(ans,dp[x][M]);
	return ;
}

int main(){
	N=read(),M=read();
    for(int i=0;i<=N;i++)
	    for(int j=0;j<=M;j++) dp[i][j]=INF;
	for(int i=1;i<N;i++){
		int u=read(),v=read();
		vec[u].push_back(v);
		vec[v].push_back(u);
	}
	dp[1][1]=0;
	dfs(1,-1);
	if(ans!=INF) printf("%d\n",ans);
	else puts("0");
}
//dp[i][j]表示i号节点的子树中隔离成为大小为j个的道路数量
//dp[i][k]=min(dp[i->son][j]+dp[i][k-j]) 
时间: 2024-12-16 18:00:20

【树形dp】Rebuilding Roads的相关文章

poj 1947 Rebuilding Roads 【树形DP】 【求至少删去树中 多少条边 使得树中节点数为P】

Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 10066   Accepted: 4595 Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. Th

POJ 1947 Rebuilding Roads (树形dp 经典题)

Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9499   Accepted: 4317 Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The

Poj 1112 Rebuilding Roads(树形DP+背包)

题意:给你由N个点构成一颗树,问要孤立出一个有P个节点的子树最少需要删除多少条边.N的范围最大为150 N的范围不大,很容易想到在树上面做背包.把每个节点都看成一个背包,然后把每个儿子节点都看成是一组物品.为什么是一组呢,那是因为假设以儿子为根的节点的子树有S个节点,那么就有S+1种情况,要么将这整棵子树舍弃,要么从这个子树中取1-S个节点. 设f[i][j]为以i为根节点的子树,孤立出以i为根节点,一共含有j个节点的子树最少需要删除的边数(不包括删除i和他父亲的连接的那条边(假设i不是根节点)

树形DP [POJ 1947] Rebuilding Roads

Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9249   Accepted: 4198 Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The

POJ题目1947 Rebuilding Roads(树形dp)

Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9957   Accepted: 4537 Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The

[POJ 1947]Rebuilding Roads (树形dp)

题目链接:http://poj.org/problem?id=1947 题目大意:给你一棵树,树上N个节点.问最少拆掉多少条边使得存在一个联通块,有P个节点. 树形dp,设计状态:dp[u][i]代表以u为根节点的剩下i个节点最少需要拆掉多少条边. 状态转移:dp[u][i+j] = min(dp[u][i+j],dp[u][i]+dp[v][j]-1); 其中v是u的儿子节点. 相当于在树上跑01背包,即每个儿子节点去掉剩下j个的但是要连上u-v边,或者不去掉剩下j个的. 代码: 1 impo

【POJ1947】Rebuilding Roads,树形DP(本文分组背包做法)

题意:给出一颗n个节点的树,要求割去一些边,使得到的树中存在m个节点的树,问最少割断多少条边. 题解: 树形DP无疑!然后就是怎么做了. 首先我们可以想到将节点分配给各子树,做一次dfs,但是做过树形DP的oiers们都知道,因为分配方式近乎于全排列,所以必死,剪枝都剪不活! 好吧,然后就有了左儿子右兄弟的优化,即重新建树,把第一个儿子归为左子节点,然后剩下的儿子都依次往该儿子的右子树上扔,不赘述了,可以自己查,因为本文并不是这种做法(动规神马的太恶心,代码复杂度太大!) 我在这里介绍一下分组背

poj1947Rebuilding Roads(树形dp)

题目:poj1949Rebuilding Roads 题意:给出一棵树,问现在要得到一颗有p个节点的子树,需要最少减掉几条边? 分析: 首先可以明确是一个树形dp题目,状态也很好定义: dp[root][j]:以root为根节点的子树,得到 j 个节点的子树需要最少减掉的边数,注意子树中必须保留root节点.否则无法dp 那么很明显的边界条件dp[root][1] = num(儿子的个数),因为要只剩一个节点的子树,那么所有的孩子都减掉,这样就为儿子的个数. 那么状态转移方程呢 dp[root]

[poj 1947] Rebuilding Roads 树形DP

Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 10653 Accepted: 4884 Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The co