Pku1947 Rebuilding Roads

题意是给一棵树,问最少删掉几条边.使得剩下的子树中有节点个数为m个的

设f[i][j]表示i号点所在的子树中选了j个点至少需要删去f[i][j]条边。

code:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define maxn 155
 7 #define inf 1061109567
 8 using namespace std;
 9 char ch;
10 int n,k,a,b,tot,ans,now[maxn],son[maxn<<1],pre[maxn<<1];
11 int siz[maxn],deg[maxn],f[maxn][maxn],tmp[maxn];
12 bool ok;
13 void read(int &x){
14     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
15     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
16     if (ok) x=-x;
17 }
18 void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
19 void dfs(int u,int fa){
20     f[u][1]=0,siz[u]=1;
21     for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
22         if (v!=fa){
23             dfs(v,u);
24             memset(tmp,63,sizeof(tmp));
25             for (int i=1;i<=siz[u];i++) tmp[i]=f[u][i]+1;
26             for (int i=1;i<=siz[u];i++)
27                 for (int j=1;j<=siz[v];j++) tmp[i+j]=min(tmp[i+j],f[u][i]+f[v][j]);
28             siz[u]+=siz[v];
29             for (int i=1;i<=siz[u];i++) f[u][i]=tmp[i];
30         }
31 }
32 int main(){
33     read(n),read(k);
34     for (int i=1;i<n;i++) read(a),read(b),put(a,b),put(b,a);
35     memset(f,63,sizeof(f));
36     dfs(1,0);
37     ans=f[1][k];
38     for (int i=2;i<=n;i++) ans=min(ans,f[i][k]+1);
39     printf("%d
",ans);
40     return 0;
41 }
原文地址:https://www.cnblogs.com/chenyushuo/p/4912335.html