poj 1947 Rebuilding Roads
http://poj.org/problem?id=1947
题意:给定N个点,之间有路N-1条,且从一点到另一点只有一种走法,问去掉几条路,可分离出由k个点组成的树
分组背包思想
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn= 205;
const int INF= 0x3f3f3f3f;
int m, n, value, dp[maxn][maxn], pre[maxn], vis[maxn], son[maxn];
struct node{
int v, next;
}edge[maxn*2];
void add(int aa, int bb){
edge[value].v= bb;
edge[value].next= pre[aa];
pre[aa]= value++;
son[aa]++;
}
void init(){
int i, j, k, aa, bb;
memset( dp, 0x3f, sizeof( dp));
memset( vis, 0, sizeof( vis));
memset( pre, -1, sizeof( pre));
memset( son, 0, sizeof( son));
value= 1;
for( i=1; i<n; i++){
scanf("%d%d", &aa, &bb);
add(aa, bb);
add(bb, aa);
}
for( i=1; i<=n; i++){
dp[i][1]= son[i];
}
}
int MIN( int x, int y){
return x<y?x:y;
}
void dfs(int u){
int i, j, k, p, mm;
for( j= pre[u]; j!= -1; j= edge[j].next){ //枚举所有的组
p= edge[j].v;
if( vis[p]) continue;
vis[p]= 1;
dfs(p);
for( i= m; i>= 0; i--){
for( k= 0; k<=m; k++){ //枚举组中所有项,注意是0...m,而不是0...son[j]
if( i-k>=0 && dp[u][i-k] < INF && dp[p][k]<INF) //注意条件
dp[u][i]= MIN(dp[u][i], (dp[u][i-k] + dp[p][k]- 2));
}
}
}
}
int main(){
// freopen("1.txt", "r", stdin);
int i, mm;
while( scanf("%d%d", &n, &m) != EOF){
init();
vis[1]= 1;
dfs(1);
for( i=1, mm= INF; i<=n; i++){
if( dp[i][m] < mm) mm= dp[i][m];
}
printf("%d\n", mm);
}
return 0;
}