poj 1947(树形dp)
题意:给出一颗树,求解截出k个连通点需要去掉的最少边树
思路:树形dp,dp[i][j] 表示以编号为i的点为根的子树包含j个连通点的最小代价。其中dp[i][1]就是该顶点的分支个数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 #define inf 0x3f3f3f 8 #define N 155 9 vector<int> g[N]; 10 int dp[N][N]; 11 int m,mi; 12 void dfs(int u){ 13 for(int i=0;i<=m;i++){ 14 dp[u][i]=inf; 15 } 16 dp[u][1]=g[u].size(); 17 for(int i=0;i<g[u].size();i++){ 18 int v=g[u][i]; 19 dfs(v); 20 for(int j=m;j>=2;j--){ 21 for(int k=j-1;k>=1;k--){ 22 dp[u][j]=min(dp[u][j],dp[u][k]+dp[v][j-k]-1); 23 } 24 } 25 } 26 if(u==1)dp[u][m]--; 27 mi=min(dp[u][m]+1,mi); 28 } 29 int main(){ 30 int n; 31 while(scanf("%d%d",&n,&m)!=EOF){ 32 memset(g,0,sizeof(g)); 33 for(int i=1;i<n;i++){ 34 int x,y; 35 scanf("%d%d",&x,&y); 36 g[x].push_back(y); 37 //g[y].push_back(x); 38 } 39 mi=inf; 40 dfs(1); 41 printf("%d\n",mi); 42 } 43 return 0; 44 }