其他分享
首页 > 其他分享> > 【luoguP3000】 [USACO10DEC]牛的健美操Cow Calisthenics

【luoguP3000】 [USACO10DEC]牛的健美操Cow Calisthenics

作者:互联网

题目链接

二分答案,判断需要断几条边,用\(f[i]\)表示以\(i\)为根的子树断边后的最长路径,对于一个点\(u\),存在\(f[v]>mid\)时就删到\(v\)的边\(f[v1]+f[v2]>mid\)时就删\(f\)较大的边,可以sort之后搞一搞

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

const int MAXN=100010;

inline int read(){
    int x=0; char c=getchar();
    while(c<'0') c=getchar();
    while(c>='0') x=x*10+c-'0',c=getchar();
    return x;
}

int n,k;

int Head[MAXN],num;
struct NODE{
    int to,nxt;
}e[MAXN<<1];

inline void add(int x,int y){
    e[++num].to=y;
    e[num].nxt=Head[x];
    Head[x]=num;
}

int f[MAXN],Cnt,mid;

inline bool cmp(int x,int y){
    return x>y;
}
void dfs(int x,int fa){
    vector<int> t; t.clear();
    for(int i=Head[x];i;i=e[i].nxt){
        int v=e[i].to;
        if(v==fa) continue;
        dfs(v,x);
        t.push_back(f[v]+1);
    }
    if(!t.size()) return;
    sort(t.begin(),t.end(),cmp);
    int l=t.size(),i=0;
    for(;i<l;++i)
        if(t[i]>mid) ++Cnt;
        else break;
    for(;i+1<l;++i)
        if(t[i]+t[i+1]>mid) ++Cnt;
        else break;
    f[x]=i<l?t[i]:0;
}

inline bool check(){
    memset(f,0,sizeof(f));
    Cnt=0;
    dfs(1,0);
    return Cnt<=k;
}

int main()
{
    scanf("%d%d",&n,&k);
    int x,y;
    for(int i=1;i<n;++i){
        x=read(); y=read();
        add(x,y); add(y,x);
    }
    int l=1,r=n;
    while(l<r){
        mid=(l+r)>>1;
        if(check()) r=mid;
        else l=mid+1;
    }
    printf("%d\n",l);
    return 0;
}

标签:Calisthenics,Cnt,return,int,else,健美操,mid,USACO10DEC,include
来源: https://www.cnblogs.com/yjkhhh/p/11743692.html