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

    本人NOIP的考试题……也是我NOIP2018唯一爆零的题目,正因如此,本人无缘NOIP2018一等奖。

    少年醒醒,都9012年了,还搞什么啊,赶紧想正解……

    本题的结构是一个树形的,因此我们可以用树形结构的相关知识解答。

    本题的题目为“最小值最大”显然是二分答案的提示,因此我们二分答案最短的一条路径mid,在满足这个条件下判断是否能找出m条道路即可。

    我们这样思考:在以i为根的子树内部,可以拼凑若干条道路(也可能没有),同时,我们选择一条不能拼出道路,且经过i点,而且最长的一条路径传给他的父亲,为他的父亲拼凑路径做贡献。

    因此,我们对于每一个点都开一个multiset,对于每个结点,把所有传上来的值 val 放进一个 multiset ,其实这些值对答案有贡献就两种情况:

    val≥k
    vala+valb≥k
    那么第一种情况可以不用放进 multiset,直接答案 +1 即可。第二种情况就可以对于每一个最小的元素,在 multiset 中找到第一个 ≥mid的数,拼成一条合法发路径,将两个数同时删去,最后把剩下最大的值传到那个结点的父亲

    为什么这种解法是正确的?有没有可能对于有些情况直接传最大的数会使答案更大?

    当然不会。这个数即使很大也只能对答案贡献加 1,在其没传上去的时候可以跟原来结点的值配对,也只能对答案贡献加 1

    这就完成了我NOIP未了的心愿……

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <set>
     6 using namespace std;
     7 inline int read() {
     8     int ret=0;
     9     int op=1;
    10     char c=getchar();
    11     while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();}
    12     while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar();
    13     return ret*op;
    14 }
    15 struct node {
    16     int next,to,dis;
    17 }a[50010<<1];
    18 int n,m,head[50010<<1],num,l=2147483647,r,sum;
    19 multiset<int> s[50010];
    20 multiset<int>::iterator it;
    21 inline void add(int from,int to,int dis) {
    22     a[++num].next=head[from];
    23     a[num].to=to;
    24     a[num].dis=dis;
    25     head[from]=num;
    26 }
    27 inline int zhijing(int now,int fa) {
    28     int sum1=0,sum2=0;
    29     for(int i=head[now];i;i=a[i].next)
    30         if(a[i].to!=fa) {
    31             sum2=max(sum2,zhijing(a[i].to,now)+a[i].dis);
    32             if(sum2>sum1) swap(sum2,sum1);
    33         }
    34     r=max(sum1+sum2,r);
    35     return sum1;
    36 }
    37 int dfs(int now,int fa,int minn) {
    38     int ret=0;
    39     s[now].clear();
    40     for(int i=head[now];i;i=a[i].next) {
    41         int v=a[i].to;
    42         if(v==fa) continue ;
    43         int val=dfs(v,now,minn)+a[i].dis;
    44         if(val>=minn) sum++;
    45         else s[now].insert(val);
    46     }
    47     while(!s[now].empty()) {
    48         if(s[now].size()==1) return max(ret,*s[now].begin());
    49         it=s[now].lower_bound(minn-*s[now].begin());
    50         if(it==s[now].begin()&&s[now].count(*it)==1) it++;
    51         if(it==s[now].end()) {
    52             ret=max(ret,*s[now].begin());
    53             s[now].erase(s[now].find(*s[now].begin()));
    54         }
    55         else {
    56             sum++;
    57             s[now].erase(s[now].find(*it));
    58             s[now].erase(s[now].find(*s[now].begin()));
    59         }
    60     }
    61     return ret; 
    62 }
    63 inline bool check(int val) {
    64     sum=0;
    65     dfs(1,0,val);
    66     return sum>=m;
    67 }
    68 int main() {
    69     n=read(); m=read();
    70     for(int i=1,x,y,z;i<n;i++) {
    71         x=read(); y=read(); z=read();
    72         add(x,y,z);
    73         add(y,x,z);
    74         l=min(l,z);
    75     }    
    76     zhijing(1,0);
    77     int ans=0;
    78     while(l<=r) {
    79         int mid=(l+r)>>1;
    80         if(check(mid)) {
    81             ans=mid;
    82             l=mid+1;
    83         }
    84         else r=mid-1;
    85     }
    86     printf("%d
    ",ans);
    87     return 0;
    88 }
    AC Code
  • 相关阅读:
    关于表单的练习和基本登录界面的制作
    css3 闪光hover
    步步为营:Asp.Net序列化与反序列化
    步步为营:Asp.Net客户端存Cookie服务端取
    步步为营:Asp.Net使用HttpWebRequest通知,抓取,采集
    PHP学习(二):PHP的魔术方法
    步步为营:SQL通用存储过程分页
    PHP学习(三):PHP面向对象概念
    PHP学习(四):PHP5.3版本的新特性
    步步为营:Asp.Net转换Unix时间戳
  • 原文地址:https://www.cnblogs.com/shl-blog/p/10769485.html
Copyright © 2011-2022 走看看