• 二分答案 + multiset || NOIP 2018 D1 T3 || Luogu P5021 赛道修建


    题面:P5021 赛道修建

    题解:二分答案,用Dfs进行判断,multiset维护。

    Dfs(x,fa,Lim)用来计算以x为根的子树中有多少符合条件的路径,并返回剩余未使用的最长路径长。

    贪心思想很显然是正确的。

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<set>
     4 #define max(a,b) ((a)>(b)?(a):(b))
     5 #define min(a,b) ((a)<(b)?(a):(b))
     6 using namespace std;
     7 inline int rd(){
     8     int x=0,f=1; char c=getchar();
     9     while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    10     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    11     return f*x;
    12 }
    13 const int maxn=5e4+5,inf=(1<<30)-5;
    14 int N,M,num_edge=0,edge_head[maxn],u,v,w,l=inf,r=0,mid;
    15 int cnt,t,a,mx;
    16 multiset<int>num[maxn];
    17 multiset<int>::iterator it;
    18 struct Edge{ int to,nx,dis; }edge[maxn<<1];
    19 inline void Add_edge(int from,int to,int dis){
    20     edge[++num_edge].nx=edge_head[from];
    21     edge[num_edge].to=to;
    22     edge[num_edge].dis=dis;
    23     edge_head[from]=num_edge;
    24 }
    25 int Dfs(int x,int fa,int Lim){
    26     num[x].clear();
    27     for(int i=edge_head[x];i;i=edge[i].nx){
    28         int y=edge[i].to;
    29         if(y==fa) continue;
    30         t=edge[i].dis+Dfs(y,x,Lim);
    31         if(t>=Lim) cnt++;
    32         else num[x].insert(t);
    33     }
    34     mx=0;
    35     while(!num[x].empty()){
    36         it=num[x].begin();
    37         a=*it; num[x].erase(it);
    38         it=num[x].lower_bound(Lim-a);
    39         if(it!=num[x].end()){
    40             cnt++;
    41             num[x].erase(it);
    42         }
    43         else mx=a;
    44     }
    45     return mx;
    46 }
    47 inline bool Check(int mid){
    48     cnt=0;
    49     Dfs(1,0,mid);
    50     if(cnt>=M) return 1;
    51     return 0;
    52 }
    53 int main(){
    54     N=rd(); M=rd();
    55     for(int i=1;i<N;i++){
    56         u=rd(); v=rd(); w=rd();
    57         Add_edge(u,v,w);
    58         Add_edge(v,u,w);
    59         l=min(l,w); r+=w;
    60     }
    61     r=r/M;
    62     while(l<=r){
    63         mid=(l+r)>>1;
    64         if(Check(mid)) l=mid+1;
    65         else r=mid-1;
    66     }
    67     printf("%d
    ",r);
    68     return 0;
    69 }
    View Code

    By:AlenaNuna

  • 相关阅读:
    oracle 监听静态注册举例解析
    oracle监听动态注册与静态注册
    oracle startup mount nomount 区别
    RAC的时间同步问题
    RAC环境TNS-12541报错处理
    Oracle参数修改是否需要重启等
    面试提纲
    Dubbo是什么
    为什么要用dubbo,dubbo和zookeeper关系
    Java的参数传递是「按值传递」还是「按引用传递」?
  • 原文地址:https://www.cnblogs.com/AlenaNuna/p/11819869.html
Copyright © 2020-2023  润新知