zoukankan      html  css  js  c++  java
  • $Noip2018/Luogu5021$ 赛道修建 二分+树形

    $Luogu$

    $Sol$

    一直以为是每个点只能经过一次没想到居然是每条边只能经过一次$....$

    首先其实这题$55$分的部分分真的很好写啊,分别是链,数的直径和菊花图,这里就不详细说了.

    使得修建的$m$条赛道中长度最小的赛道长度最大有了这句话显然就要考虑考虑二分.现在就是要考虑如何判断了.

    任意选择结点作为根建树.注意到一条赛道的组成其实只有两种,一种是一条简单的由浅到深的链,另一种是由深到浅再到深这样的折了一下的链.考虑由深到浅的处理结点.对于每个结点,把子结点上传的链长加上父与子之间的边权加入$mutiset$.首先找到值已经大于等于$mid$的,直接累计答案.然后考虑内部匹配,从小到大扫,找到另一个最小的使得两者相加大于等于$mid$的值,删去这俩结点并且累计答案.最后向父结点上传剩余的链里面最长的就行.

    $Code$

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<set>
    #include<algorithm>
    #define il inline
    #define Rg register
    #define go(i,a,b) for(Rg int i=a;i<=b;++i)
    #define yes(i,a,b) for(Rg int i=a;i>=b;--i)
    #define e(i,u) for(Rg int i=b[u];i;i=a[i].nt)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define v(i) a[i].v
    #define w(i) a[i].w
    #define ll long long
    #define db double
    #define IT multiset<ll>::iterator
    #define inf 2147483647
    using namespace std;
    il int read()
    {
        Rg int x=0,y=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
        return x*y;
    }
    const int N=50010;
    int n,m,b[N],ct;
    ll d1[N],d2[N],l=inf,r,mid,as;
    struct node{int v,w,nt;}a[N*2];
    il void add(int u,int v,int w){a[++ct]=(node){v,w,b[u]};b[u]=ct;}
    il void dfs1(int u,int ft)
    {
        e(i,u)
        {
            if(v(i)==ft)continue;
            dfs1(v(i),u);
            if(d1[v(i)]+w(i)>d1[u]){d2[u]=d1[u];d1[u]=d1[v(i)]+w(i);}
            else d2[u]=max(d2[u],d1[v(i)]+w(i));
        }
    }
    il ll dfs(int u,int fa)
    {
        multiset<ll>q;q.clear();
        e(i,u)
        {
            if(v(i)==fa)continue;
            ll val=dfs(v(i),u)+w(i);
            if(val>=mid)ct++;
            else q.insert(val);
        }
        ll ret=0;
        while(q.size())
        {
            IT i=q.begin();
            IT j=q.lower_bound(mid-*i);
            if(((i==j)&&q.count(*i)==1))j++;
            if(j==q.end()){ret=max(ret,*i);q.erase(i);continue;}
            ct++;q.erase(q.find(*i));q.erase(q.find(*j));
        }
        return ret;
    }
    il bool ck()
    {
        ct=0;dfs(1,0);
        if(ct>=m)return 1;return 0;
    }
    int main()
    {
        n=read(),m=read();
        go(i,1,n-1){Rg int u=read(),v=read(),w=read();add(u,v,w);add(v,u,w);l=min(l,(ll)w);}
        dfs1(1,0);
        go(i,1,n)r=max(r,d1[i]+d2[i]);
        if(m==1){printf("%lld
    ",r);return 0;}
        r+=1;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(ck())as=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%lld
    ",as);
        return 0;
    }
    View Code

     

    光伴随的阴影
  • 相关阅读:
    Cannot find class [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter]
    HTTP的长连接和短连接
    Nginx(三)nginx 反向代理
    Nginx(四)nginx 负载均衡
    postgresql 数据库 INSERT 或 UPDATE 大量数据时速度慢的原因分析
    低层次父母,喜欢不停地“讲道理”,而高层次父母,会做2件事
    oracle数据库数据量如何计算,怎么查看oracle数据库数据量大小?
    Git的eclipse插件(下载、抓取、提交、恢复、比较)
    Linux 上 定时备份postgresql 数据库的方法
    Nginx(二)nginx.conf 配置文件
  • 原文地址:https://www.cnblogs.com/forward777/p/11403455.html
Copyright © 2011-2022 走看看