当前位置: 代码迷 >> 综合 >> poj 1947 Rebuilding Roads 树型dp
  详细解决方案

poj 1947 Rebuilding Roads 树型dp

热度:52   发布时间:2024-01-19 06:30:27.0

题意:

给一个有n个结点的树,要去掉一些边分离出一棵恰有p个结点的子树,求去掉的最少边数。

思路:

树型dp,dp[root][x]表示root子树得到x个结点的子树需去掉的最少边数,设点root有num个孩子,那么经过num个阶段就能确定dp[root][x]的值,dp即可,用滚动数组节省空间。

代码:

//poj 1947
//sepNINE
#include <iostream>
using namespace std;
const int maxN=256; 
int n,p;
int par[maxN],bro[maxN],son[maxN];
int dp[maxN][maxN];
void dfs(int root)
{int i,j;for(i=1;i<=p;++i)dp[root][i]=100000;dp[root][1]=0;int s=son[root];while(s){dfs(s);for(i=p;i>=1;--i){dp[root][i]=dp[root][i]+1;int tmp=dp[root][i];for(j=1;j<i;++j)tmp=min(tmp,dp[root][j]+dp[s][i-j]);dp[root][i]=tmp;}s=bro[s];}	return ;
}int main()
{scanf("%d%d",&n,&p);int i,a,b;memset(par,0,sizeof(par));memset(bro,0,sizeof(bro));memset(son,0,sizeof(son));for(i=1;i<n;++i){scanf("%d%d",&a,&b);par[b]=1;		bro[b]=son[a];son[a]=b;}int root;for(i=1;i<=n;++i)if(par[i]==0)root=i;dfs(root);int ans=INT_MAX;for(i=1;i<=n;++i)if(par[i]==0)ans=min(ans,dp[i][p]);elseans=min(ans,dp[i][p]+1);printf("%d",ans);
}


  相关解决方案