zoukankan      html  css  js  c++  java
  • 【noip2018】【luogu5021】赛道修建

    题目描述

    C 城将要举办一系列的赛车比赛。在比赛前,需要在城内修建 mm 条赛道。

    C 城一共有 nn 个路口,这些路口编号为 1,2,…,n1,2,,n,有 n-1n1 条适合于修建赛道的双向通行的道路,每条道路连接着两个路口。其中,第 ii 条道路连接的两个路口编号为 a_iai  b_ibi,该道路的长度为 l_ili。借助这 n-1n1 条道路,从任何一个路口出发都能到达其他所有的路口。

    一条赛道是一组互不相同的道路 e_1,e_2,…,e_ke1,e2,,ek,满足可以从某个路口出发,依次经过 道路 e_1,e_2,…,e_ke1,e2,,ek(每条道路经过一次,不允许调头)到达另一个路口。一条赛道的长度等于经过的各道路的长度之和。为保证安全,要求每条道路至多被一条赛道经过。

    目前赛道修建的方案尚未确定。你的任务是设计一种赛道修建的方案,使得修建的 mm 条赛道中长度最小的赛道长度最大(即 mm 条赛道中最短赛道的长度尽可能大)

    输入输出格式

    输入格式:

    输入文件第一行包含两个由空格分隔的正整数 n,mn,m,分别表示路口数及需要修建的 赛道数。

    接下来 n-1n1 行,第 ii 行包含三个正整数 a_i,b_i,l_iai,bi,li,表示第 ii 条适合于修建赛道的道 路连接的两个路口编号及道路长度。保证任意两个路口均可通过这 n-1n1 条道路相互到达。每行中相邻两数之间均由一个空格分隔。

    输出格式:

    输出共一行,包含一个整数,表示长度最小的赛道长度的最大值。

    【数据规模与约定】

    对于所有的数据, 2 ≤ n ≤ 50,0002n50,000 1 ≤ m ≤ n-11mn1 1 ≤ a_i,b_i ≤ n1ai,bin 1 ≤ l_i ≤ 10,0001li10,000

    题解:

           题意即求一个k段不相交路径长度最小值的最大值;

           二分这个最大的最小值mid,那么要求判断是否有一种方案可以分出>=k条路径使得权值都>=mid;

          树形dp  : 当做到节点u,要么u的所有儿子都一定成为了路径,要么至多有一条可以向上延伸的路径;

          这样如果可以在u形成>=mid的路径,那么一定比此时不形成路径往上连更优;

          记录每个点可以往上连的权值val,考虑u的儿子v,u,v之间的边为E[i]  (代码风格,忍受一下。。)

          val[v]+E[i].w >= mid 直接统计为一条合法路径;

          否则把左边存在一个数组里,可以知道要形成路径只能两两配对,排序后二分可以确定最大的对数;

          注意未配对的最大的数可能可以替换已配对的权值,找到最大可替换数设置成val[u](注意细节)

          复杂度   $O(n log^2 n)$

     

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<vector>
     4 #include<algorithm>
     5 #define inf 0x3f3f3f3f
     6 #define rg register 
     7 #define il inline 
     8 #define Run(i,l,r) for(int i=l;i<=r;i++)
     9 using namespace std;
    10 const int N=50500;
    11 int n,k,o,hd[N],mid,val[N],sum,p[N];
    12 vector<int>g[N];
    13 struct Edge{int v,nt,w;}E[N<<1];
    14 void adde(int u,int v,int w){
    15     E[o]=(Edge){v,hd[u],w};hd[u]=o++;
    16     E[o]=(Edge){u,hd[v],w};hd[v]=o++; 
    17 }
    18 bool check2(int u,int Mid){
    19     int cnt=g[u].size();
    20     int p=cnt-(Mid<<1); 
    21     for(int i=1;i<=Mid;i++){
    22         if(g[u][p+i-1]+g[u][cnt-i]<mid)return false;
    23     }
    24     return true;
    25 }
    26 void dfs(int u,int fa){
    27     g[u].clear();
    28     val[u]=0;
    29     for(int i=hd[u];i;i=E[i].nt){
    30         int v=E[i].v;
    31         if(v==fa)continue;
    32         dfs(v,u);
    33         int t=E[i].w+val[v];
    34         if(t>=mid)sum++;
    35         else g[u].push_back(t); 
    36     }
    37     int cnt=(int)g[u].size();
    38     if(!cnt)return;
    39     sort(g[u].begin(),g[u].end());
    40     int l=0,r=cnt>>1;
    41     while(l<r){
    42         int Mid=(l+r+1)>>1;
    43         if(check2(u,Mid))l=Mid;
    44         else r=Mid-1;
    45     }
    46     sum+=l;
    47     if((l<<1)==cnt)return;
    48     for(int i=0;i<l;i++){
    49         int t1=cnt-(l<<1)+i;
    50         int t2=cnt-1-i;
    51         p[t1]=t2;
    52         p[t2]=t1;
    53     }
    54     int t;
    55     for(t=cnt-(l<<1);t<cnt&&g[u][t-1]+g[u][p[t]]>=mid;t++){
    56         p[p[t]]=t-1;
    57         p[t-1]=p[t]; 
    58     }
    59     t--;
    60     return void(val[u]=g[u][t]);
    61 }
    62 bool check1(){
    63     sum=0;dfs(1,0);
    64     return sum>=k;
    65 }
    66 int main(){
    67     freopen("track.in","r",stdin);
    68     freopen("track.out","w",stdout);
    69     scanf("%d%d",&n,&k);
    70     int l=inf,r=0;
    71     o=1;
    72     for(rg int i=1,u,v,w;i<n;i++){
    73         scanf("%d%d%d",&u,&v,&w);
    74         r+=w; l=min(l,w);
    75         adde(u,v,w);
    76     }
    77     while(l<r){
    78         mid=(l+r+1)>>1;
    79         if(check1())l=mid;
    80         else r=mid-1;
    81     }
    82     printf("%d
    ",l);
    83 }//by tkys_Austin;
    View Code
  • 相关阅读:
    linux下安装字体解决爬虫截图乱码问题
    开线程爬取黑猫里的阿里投诉信息
    CSS以及JS各种库的在线CDN引用地址
    linux系统下安装PHP扩展pcntl
    linux系统下安装Git
    linux进行文件vim编辑时没有退出文件直接关闭出现E325: ATTENTION Found a swap file by the name "/usr/local/php/etc/.php.ini.swp"
    windows安装redis和PHP redis扩展
    找回phpstorm删除文件/文件夹(phpstorm删除文件/文件夹的恢复)
    YII报错笔记:<pre>PHP Notice &#039;yiiaseErrorException&#039; with message &#039;Uninitialized string offset: 0&#039; in /my/test/project/iot/vendor/yiisoft/yii2/base/Model.php:778
    linux下使用svn创建版本库和权限管理
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10014642.html
Copyright © 2011-2022 走看看