P1272 重建道路

l i n k link link

这道题出的其实挺好的
显然是一个树形 d p dp dp问题
最开始想复杂了
后来发现很简单
一直以为是n^3做法
我们用 d p u , k dp_{u,k} dpu,k表示在以 u u u为根的子树中,剔除 k k k个的最小需要切的边数
那么初值就是 d p u , 1 = d u u dp_{u,1}=du_u dpu,1=duu
转移就是
d p u , k = min ⁡ { d p v , j + d p u , k − j − 2 } , v ∈ s o n ( u ) , j ≤ k dp_{u,k}=\min\{dp_{v,j}+dp_{u,k-j}-2\},v\in son(u) ,j\leq k dpu,k=min{dpv,j+dpu,kj2},vson(u),jk
注意我们为什么需要 − 2 -2 2呢,因为我们在 u , v u,v u,v这里先是默认把他删掉了,然后我们再把他连上,所以要 − 2 -2 2
答案就是 min ⁡ { d p u , p } \min\{dp_{u,p}\} min{dpu,p}
其实就是背包嘛

#include <bits/stdc++.h>
using namespace std;

# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)

typedef long long ll;

const int N=205;

template<typename T> void read(T &x){
   x=0;int f=1;
   char c=getchar();
   for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
   for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
    x*=f;
}

int n,p;
int head[N],cnt;
int f[N][N],ans=INT_MAX;
int siz[N],du[N];

struct Edge{
    int to,next;
}e[N*N];

void add(int x,int y){
    e[++cnt]=(Edge){y,head[x]},head[x]=cnt;
}

void dfs(int u,int fa){
    siz[u]=1,f[u][1]=du[u];
    RepG(i,u){
        int v=e[i].to;
        if(v==fa)continue;
        dfs(v,u);
        _Rep(k,min(siz[u],p),1)
            for(int j=1;j<=siz[v]&&j+k<=p;j++)
                f[u][k+j]=min(f[u][k+j],f[u][k]+f[v][j]-2);
        siz[u]+=siz[v];
    }
    ans=min(ans,f[u][p]);
}

int main()
{
    memset(head,-1,sizeof(head));
    memset(f,0x3f,sizeof(f));
    read(n),read(p);
    if(n==1)return puts("0"),0;
    if(!p)return puts("0"),0;
    Rep(i,1,n-1){
        int x,y;
        read(x),read(y);
        du[x]++,du[y]++;
        add(x,y),add(y,x);
    }
    dfs(1,0);
    printf("%d\n",ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值