标签:
| Time Limit: 1000MS | Memory Limit: 30000K | |
| Total Submissions: 9496 | Accepted: 4316 |
Description
Input
Output
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
Source
给出n个节点的树,给出值m。问最少删除几条边可以得到节点个数为m的子树。
树状dp,统计出以节点i为根的子树得到节点个数为j的子树最少删除的边数。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define INF 0x3f3f3f3f
struct node {
int v , next ;
}edge[160] ;
int head[160] , cnt ;
int c[160][160] , sum[160];
void add(int u,int v) {
edge[cnt].v = v ;
edge[cnt].next = head[u] ;
head[u] = cnt++ ;
}
void dfs(int u)
{
sum[u] = 1 ;
if( head[u] == -1 )
{
c[u][ sum[u] ] = 0 ;
return ;
}
int i , j , k , v , temp ;
for(i = head[u] ; i != -1 ; i = edge[i].next) {
v = edge[i].v ;
dfs(v) ;
sum[u] += sum[v] ;
}
c[u][ sum[u] ] = 0 ;
for(i = head[u] ; i != -1 ; i = edge[i].next) {
v = edge[i].v ;
c[v][0] = 1 ;
for(j = 0 ; j <= sum[u] ; j++) {
for(k = 0 ; k <= sum[v] ; k++) {
temp = sum[v] - k ;
if( j >= temp )
c[u][ j-temp ] = min( c[u][j-temp],c[u][j]+c[v][k] ) ;
}
}
c[v][0] = INF ;
}
return ;
}
int main() {
int n , p , i , u , v ;
memset(head,-1,sizeof(head)) ;
memset(c,INF,sizeof(c)) ;
memset(sum,0,sizeof(sum)) ;
cnt = 0 ;
scanf("%d %d", &n, &p) ;
add(0,1) ;
for(i = 0 ; i < n-1 ; i++) {
scanf("%d %d", &u, &v) ;
add(u,v) ;
}
dfs(0) ;
int min1 = c[1][p] ;
for(i = 2 ; i <= n ; i++) {
min1 = min(min1,c[i][p]+1) ;
}
printf("%d\n", min1) ;
return 0 ;
}
poj1947--Rebuilding Roads(树状dp)
标签:
原文地址:http://blog.csdn.net/winddreams/article/details/44104131