$NOIP2018$赛道修建

时间:2019-11-14
本文章向大家介绍$NOIP2018$赛道修建,主要包括$NOIP2018$赛道修建使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

\(NOIP2018\)赛道修建

树形结构不带树上算法走典型。

\(DFS\),即可,考虑的方向不能脱离树状结构。

即考虑一棵子树中分出的路线一定是独立的,而那些没用的边可以传上去作为备选答案。

再考虑一个贪心,我们每次上传最大的即可。

#include<bits/stdc++.h>
using namespace std;
namespace AE86
{
    const int bufl=1<<15;
    char buf[bufl],*s=buf,*t=buf;
    inline int fetch()
    {
        if(s==t){t=(s=buf)+fread(buf,1,bufl,stdin);if(s==t)return EOF;}
        return*s++;
    }
    inline int read()
    {
        int a=0,b=1,c=fetch();
        while(!isdigit(c)) b^=c=='-',c=fetch();
        while(isdigit(c)) a=a*10+c-48,c=fetch();
        return b?a:-a;
    }
}
const int N=5e4+10;
int n,m,num_edge,Sum,Ans;
int head[N<<1],Dis[N];
struct Edge{int next,to,dis;} edge[N<<1];
inline void Add(int from,int to,int dis)
{
    edge[++num_edge].next=head[from];
    edge[num_edge].dis=dis;
    edge[num_edge].to=to;
    head[from]=num_edge;
}
inline int Dfs(int pos,int fth,int k)
{
    multiset<int> S; S.clear();
    for(int i=head[pos];i;i=edge[i].next)
        if(edge[i].to!=fth)
        {
            int Bac=Dfs(edge[i].to,pos,k)+edge[i].dis;
            if(Bac>=k) Ans++;
            else S.insert(Bac);
        }
    int Max=0;
    while(S.size())
    {
        if(S.size()==1) return max(Max,*S.begin());
        multiset<int>::iterator It=S.lower_bound(k-*S.begin());
        if(It==S.begin()&&S.count(*It)==1) It++;
        if(It==S.end()) Max=max(Max,*S.begin()),S.erase(*S.begin());
        else Ans++,S.erase(It),S.erase(S.begin());
    }
    return Max;
}
inline bool Check(int k)
{
    Ans=0; Dfs(1,0,k);
    if(Ans>=m) return 1;
    else return 0;
}
inline void Dfs_For_Dia(int pos,int fth)
{
    for(int i=head[pos];i;i=edge[i].next)
        if(edge[i].to!=fth)
        {
            Dfs_For_Dia(edge[i].to,pos);
            Sum=max(Sum,Dis[pos]+Dis[edge[i].to]+edge[i].dis);
            Dis[pos]=max(Dis[pos],Dis[edge[i].to]+edge[i].dis);
        }
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("A.in","r",stdin);
#endif
    n=AE86::read(),m=AE86::read();
    for(int i=1,U,V,D;i<n;i++)
        U=AE86::read(),V=AE86::read(),D=AE86::read(),Add(U,V,D),Add(V,U,D);
    Dfs_For_Dia(1,0);int l=0,r=Sum;
    while(l<r)
    {
        int mid=(l+r+1)>>1;
        if(Check(mid)) l=mid;
        else r=mid-1;
    }
    printf("%d\n",l);
}

原文地址:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/11857841.html