标签:
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