您的位置:首页 > 产品设计 > UI/UE

Pku1947 Rebuilding Roads

2015-10-26 20:33 337 查看
题意是给一棵树,问最少删掉几条边.使得剩下的子树中有节点个数为m个的

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

code:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 155
#define inf 1061109567
using namespace std;
char ch;
int n,k,a,b,tot,ans,now[maxn],son[maxn<<1],pre[maxn<<1];
int siz[maxn],deg[maxn],f[maxn][maxn],tmp[maxn];
bool ok;
void read(int &x){
for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
if (ok) x=-x;
}
void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
void dfs(int u,int fa){
f[u][1]=0,siz[u]=1;
for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if (v!=fa){
dfs(v,u);
memset(tmp,63,sizeof(tmp));
for (int i=1;i<=siz[u];i++) tmp[i]=f[u][i]+1;
for (int i=1;i<=siz[u];i++)
for (int j=1;j<=siz[v];j++) tmp[i+j]=min(tmp[i+j],f[u][i]+f[v][j]);
siz[u]+=siz[v];
for (int i=1;i<=siz[u];i++) f[u][i]=tmp[i];
}
}
int main(){
read(n),read(k);
for (int i=1;i<n;i++) read(a),read(b),put(a,b),put(b,a);
memset(f,63,sizeof(f));
dfs(1,0);
ans=f[1][k];
for (int i=2;i<=n;i++) ans=min(ans,f[i][k]+1);
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: