AGC001 Shorten Diameter

题目

传送门

题目大意

我们称一个直径不超过 K K K的数为好树,给定一个 N ( N ≤ 2000 ) N(N\leq 2000) N(N2000)个结点的无根树,至少需要删除多少个点,它才能变成一个好树?

思路

根据树的直径的性质:

  • K K K是偶数,枚举一个点作为好树的中心,那么这个点到任何一个点的距离都应小于等于 K 2 \dfrac{K}{2} 2K,需要删掉的点就是到它距离超过这么多的点。
  • K K K是奇数,枚举一条边 ( u , v ) (u,v) (u,v)作为好树的中心边,那么任何一个点到 u u u或到 v v v的距离都应小于等于 K − 1 2 \dfrac{K-1}{2} 2K1,请自行脑补画面。

时间复杂度 O ( N 2 ) O(N^2) O(N2)

代码

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

#define MAXN 2000
struct Edge{
    int v,u;
}E[MAXN+5];
int N,K;
vector<int> G[MAXN+5];

//有多少个点需要删掉
int dfs(int u,int f,int MaxD,int D){
    int ret=0;
    if(D>MaxD)
        ret++;
    for(int i=0;i<int(G[u].size());i++){
        int v=G[u][i];
        if(v!=f)
            ret+=dfs(v,u,MaxD,D+1);
    }
    return ret;
}

int main(){
    scanf("%d%d",&N,&K);
    for(int i=1;i<N;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
        E[i]=(Edge){u,v};
    }
    int Ans=N;
    if(K&1)//两种情况
        for(int i=1;i<N;i++)
            Ans=min(Ans,dfs(E[i].u,E[i].v,K/2,0)+dfs(E[i].v,E[i].u,K/2,0));
    else
        for(int i=1;i<=N;i++)
            Ans=min(Ans,dfs(i,-1,K/2,0));
    printf("%d",Ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值