zoukankan      html  css  js  c++  java
  • 题解 洛谷 P6142 【[USACO20FEB]Delegation P】

    赛道修建类似,先对(k)进行二分,将最值问题转化为判定问题。

    在判定一个(k)是否合法时,贪心去考虑,一个节点下面的若干条链在合并时,一条链肯定和另一条使它合并后恰好满足长度限制的链合并最优。因此我们用(multiset)来进行维护,一条长度为(len)的链,去查询第一条长度大于等于(k-len)的链,若找不到,即不合法。

    再考虑到一个非根节点在合并链时,是可以有一条链无法合并,其它链两两配对,那么剩下那个链就往上继续寻找配对即可,但根节点肯定是要两两配对。

    所以在合并时,可以增加一个长度为(0)的链,来使非根节点的链数量为奇数,使根节点的链数量为偶数,方便一些细节的处理。

    实现就看代码吧。

    (code:)

    #include<bits/stdc++.h>
    #define maxn 200010
    using namespace std;
    typedef multiset<int>::iterator mul;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n;
    bool flag;
    int f[maxn];
    struct edge
    {
        int to,nxt;
    }e[maxn];
    int head[maxn],edge_cnt=1;
    void add(int from,int to)
    {
        e[++edge_cnt]=(edge){to,head[from]};
        head[from]=edge_cnt;
    }
    void dfs(int x,int fa,int len)
    {
    	if(!flag) return;
        multiset<int> s;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(y==fa) continue;
    		dfs(y,x,len);
    		s.insert(f[y]+1);
    	}
        int size=s.size();
        bool tag=false;
        if((x==1&&size&1)||(x!=1&&!(size&1))) s.insert(0);
        while(!s.empty())
        {
            if(!flag) break;
            int l1;
            mul t1=s.begin(),t2;
            l1=*t1,s.erase(t1),t2=s.lower_bound(len-l1);
            if(x==1)
            {
                if(t2==s.end())
                {
                    flag=false;
                    break;
                }
                s.erase(t2);
            }
            else
            {
                if(t2==s.end()&&tag)
                {
                    flag=false;
                    break;
                }
                if(t2==s.end()&&!tag) f[x]=l1,tag=true;
                if(t2!=s.end()) s.erase(t2);
            }
        }
    }
    bool check(int x)
    {
        flag=true,memset(f,0,sizeof(f)),dfs(1,0,x);
        return flag;
    }
    int main()
    {
        read(n);
        for(int i=1;i<n;++i)
        {
            int a,b;
            read(a),read(b);
            add(a,b),add(b,a);
        }
        int l=1,r=n-1,ans=1;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(check(mid)) ans=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%d",ans);
        return 0;
    }
    
  • 相关阅读:
    python之接口与抽象类
    python之内置函数与匿名函数
    python之常用模块
    python之块包导入
    python之协程函数、递归、二分法
    Ios证书申请流程
    VUE + vue-cli + webpack 创建新项目(2)
    VUE + vue-cli + webpack 创建新项目
    布局的几种方式(静态布局、自适应布局、流式布局、响应式布局、弹性布局)
    浅谈rem布局和vm布局
  • 原文地址:https://www.cnblogs.com/lhm-/p/12631812.html
Copyright © 2011-2022 走看看