Rebuilding Roads - POJ 1947 树形dp

来源:互联网 发布:洛阳淘宝运营培训机构 编辑:程序博客网 时间:2024/05/08 19:18

Rebuilding Roads
Time Limit: 1000MS Memory Limit: 30000KTotal Submissions: 8866 Accepted: 4000

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 61 21 31 41 52 62 72 84 94 104 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.] 

题意:让你将一棵树的某些边拆开,使得可以形成P个节点的树,问你最少需要拆几条边。

思路:dp[i][j]表示以i作为根节点,保留j个节点最少拆几条边。转移方程为dp[u][s]=min(dp[u][s],dp[u][s-j]+dp[v][j]-1);   v代表他的子节点。因为原dp[u][s-j]是把v当做是一个点来看的,所以当你去拆v中的边的时候,uv连接的边不用拆,所以-1。然后ans的解释看代码上的注释。

AC代码如下:

#include<cstdio>#include<cstring>#include<vector>using namespace std;int dp[160][160],n,p,INF=0x3f3f3f3f,ans=INF,tot[160];vector<int> vc[160];int dfs(int u){ int i,j,k,v,s;  tot[u]=1;  for(i=0;i<vc[u].size();i++)    tot[u]+=dfs(vc[u][i]);  dp[u][1]=vc[u].size();  for(i=0;i<vc[u].size();i++)  { v=vc[u][i];    for(s=tot[u];s>=1;s--)    { for(j=1;j<s && j<=tot[v];j++)       dp[u][s]=min(dp[u][s],dp[u][s-j]+dp[v][j]-1);    }  }  if(tot[u]>=p)   if(u==1)    ans=min(ans,dp[u][p]);   else    ans=min(ans,dp[u][p]+1);//当u不为根节点的时候,需要把u上面的边拆掉,形成子树。  return tot[u];}int main(){ int i,j,k,u,v;  scanf("%d%d",&n,&p);  memset(dp,INF,sizeof(dp));  for(i=2;i<=n;i++)  { scanf("%d%d",&u,&v);    vc[u].push_back(v);  }  dfs(1);  printf("%d\n",ans);}




0 0
原创粉丝点击