题目描述

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

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

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

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

输入输出格式

输入格式:

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

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

输出格式:

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

题意 一棵树 给定建m条赛道 要使得这m条赛道中最短的赛道最长 赛道上每一条边只经过一次

解题方法

m = 1 贪心求树的直径就完事了

链上部分分 二分 最短的赛道的长度 上界为直径 下界为1 nlog所有边边长和   完事了

菊花图 将权值排序 将最大的与第m大的组成赛道 第二大与第m-1大组成赛道  ....  完事了

55pts get

满分做法

我们要做的是在使最多的儿子对答案做出贡献的同时,传递上去的值是最大的

具体做法如下

二分最短赛道的长度

1.每个树节点 保存子节点传来的最大值加上与该节点的连边长度。若该值大于等于k 则答案+1。 若小于k 将该值插入multiset集合 (将该值往上传)。

2.然后处理multiset集合中的元素 若集合仅有一个元素 那将该元素传至父节点(该数是传至父节点的最大的数)

若有多个元素 找到第一个大于等于k-begin的数 (即能和begin组成一条赛道的数)

如果该数等于begin且begin仅有一个数 (这种情况一般是begin>k-begin) 迭代器++

找下一个大于他的数 如果迭代器等于end 即找不到与begin组成大于k的数 将begin删除 如果找到 begin和该数一同删除 答案++ 然后就解决啦!

#include <cstdio>
#include <algorithm>
#include <set>
#include <iostream>
using namespace std;
const int M = ;
int head[M],nxt[M],to[M],c[M];
int val;
int ans;
int size;
int n ,m;
int zj,gd;
multiset<int> s[M];
multiset<int> ::iterator it;
void add(int u ,int v,int w)
{
nxt[++size] = head[u];
head[u] = size;
to[size] = v;
c[size] = w;
}
void dfs(int now,int fa,int k) // 求树的直径
{
if(k > zj) gd = now,zj = k;
for(int i = head[now];i;i = nxt[i])
{
if(to[i] == fa) continue;
dfs(to[i],now,k+c[i]);
}
}
int dfs1(int now,int fa,int k)
{
s[now].clear();
for(int i = head[now];i;i = nxt[i])
{
if(to[i] == fa) continue;
val = dfs1(to[i],now, k) + c[i];
if(val >= k) ans++;
else s[now].insert(val);
}
int Max = ;
while(!s[now].empty())
{
if(s[now].size() == ) return max(Max,*s[now].begin());
it = s[now].lower_bound(k-*s[now].begin());
if(it == s[now].begin()&&s[now].count(*it) == ) it++;
if(it == s[now].end())
{
Max = max(Max,*s[now].begin());
s[now].erase(s[now].find(*s[now].begin()));
}
else{
ans++;
s[now].erase(s[now].find(*s[now].begin()));
s[now].erase(s[now].find(*it));
}
}
return Max;
}
bool check(int k)
{
ans = ;
dfs1(,,k);
if(ans >= m) return true;
else return false;
}
int main(){
scanf("%d%d",&n,&m);
int u , v , w;
for(int i = ;i <= n - ;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u ,v , w);
add(v , u ,w);
}
dfs(,,); //
dfs(gd,,); // 两遍dfs求树的直径
int l = ,r = zj;
while(l < r)
{
int mid = (l + r + ) >> ;
if(check(mid)) l = mid;
else r = mid - ;
}
printf("%d",l);
}

noip2018 D1T3 赛道修建的更多相关文章

  1. NOIP2018 D1T3赛道修建

    题目链接:Click here Solution: 最小值最大,考虑二分一个答案\(k\) 考虑在子树内先匹配,最后传递一个值给自己的父亲(因为每条边只能用一次,所以一颗子树最多传递一个值) 那么我们 ...

  2. noip 2018 D1T3 赛道修建

    noip 2018 D1T3 赛道修建 首先考虑二分答案,这时需要的就是对于一个长度求出能在树中选出来的最多的路径条数.考虑到一条路径是由一条向上的路径与一条向下的路径构成,或者仅仅是向上或向下的路径 ...

  3. 题解 NOIP2018【赛道修建】—— 洛谷

    这道题有一点点树上dp的意思(大佬轻喷 我刚拿到这道题的时候毫无头绪,只知道这道题要二分答案 为什么是二分答案??? 题目: 目前赛道修建的方案尚未确定.你的任务是设计一 种赛道修建的方案,使得修建的 ...

  4. [NOIP2018 TG D1T3]赛道修建

    题目大意:$NOIP2018\;TG\;D1T3$ 题解:题目要求最短的赛道的长度最大,可以想达到二分答案,接着就是一个显然的树形$DP$. 发现对于一个点,它子树中若有两条链接起来比要求的答案大,一 ...

  5. $Noip2018/Luogu5021$ 赛道修建 二分+树形

    $Luogu$ $Sol$ 一直以为是每个点只能经过一次没想到居然是每条边只能经过一次$....$ 首先其实这题$55$分的部分分真的很好写啊,分别是链,数的直径和菊花图,这里就不详细说了. 使得修建 ...

  6. 「NOIP2018」赛道修建

    传送门 Luogu 解题思路 一眼先二分(上界树的直径,下界最小边权),然后再考虑 \(\text{DP}\). 对于当前节点 \(u\),在它的所有儿子中分别返回一条匹配不完的长度最大的路径 \(M ...

  7. Luogu5021 [NOIP2018]赛道修建

    Luogu5021 [NOIP2018]赛道修建 一棵大小为 \(n\) 的树,边带权.选 \(m\) 条链使得长度和最小的链最大. \(m<n\leq5\times10^4\) 贪心,二分答案 ...

  8. [NOIp2018提高组]赛道修建

    [NOIp2018提高组]赛道修建 题目大意: 给你一棵\(n(n\le5\times10^4)\)个结点的树,从中找出\(m\)个没有公共边的路径,使得第\(m\)长的路径最长.问第\(m\)长的路 ...

  9. 【LG5021】[NOIP2018]赛道修建

    [LG5021][NOIP2018]赛道修建 题面 洛谷 题解 NOIP之前做过增强版还没做出来\(QAQ\) 一看到题目中的最大值最小,就很容易想到二分答案 重点是考虑如何\(check\) 设\( ...

随机推荐

  1. 【bzoj 3252】攻略

    题意 我们想到一个贪心,就是每次找到根路径前缀和最大的一个点,取走这条路径,同时把这条路径上的点权变成\(0\) 正确性显然 进一步发现我们需要从树上选择\(m\)条链使得链的总和最大 于是我们考虑换 ...

  2. regex_iterator

    绝对不能在循环中通过regex_search获取模式在源字符串所有的实例:应该改为regex_iterator或则regex_token_iterator,一般情况下需要位一个特定的容器来指定一个尾迭 ...

  3. [转]地图投影的N种姿势

    此处直接给出原文链接: 1.地图投影的N种姿势 2.GIS理论(墨卡托投影.地理坐标系.地面分辨率.地图比例尺.Bing Maps Tile System)

  4. MySQL数据库启停

    坑1:net start mysql 提示:服务名无效 1.win+R打开运行窗口,输入services.msc 2.在其中查看mysql的服务名,我的是MySQL55 3.以管理员身份打开cmd,输 ...

  5. 学记笔记 $\times$ 巩固 · 期望泛做$Junior$

    最近泛做了期望的相关题目,大概\(Luogu\)上提供的比较简单的题都做了吧\(233\) 好吧其实是好几天之前做的了,不过因为太颓废一直没有整理-- \(Task1\) 期望的定义 在概率论和统计学 ...

  6. java学习笔记-基础篇

    Java基础篇 1—12 常识 13 this关键字 14参数传递 16 继承 17 访问权限 28—31异常 1—12 常识 1.文件夹以列表展示,显示扩展名,在地址栏显示全路径 2.javac编译 ...

  7. OO第一次总结作业

    第一次OO博客作业 前言 面向对象课程已经经过了4周的时间.前三次作业全部是关于多项式求导的相关内容,内容由易到难,同时我也开始逐渐深入感受学习面向对象的各项特征,逐渐将自己的编程风格从C向真正的面向 ...

  8. IIS中多域名多网站的设置方法

    一个 IP 可以绑定多个域名.如您需要实现多个域名访问同一个网站,只需就不同域名添加 A 记录指向同一个 IP 即可. 如您需要实现多个域名访问同一虚拟服务器上不同网站,也需要就不同域名添加 A 记录 ...

  9. 如何补装oracle的sample schema

    SQL>@ORACLE_HOME/rdbms/admin/utlsampl.sql; 似乎不够完整,等待补充.

  10. 【JLOI2013】卡牌游戏

    题面 题解 概率$dp$ 设$f[i][j]$表示还剩$i$个人时,第$j$个人获胜的概率. 边界$f[1][1] = 1$ 转移: 枚举庄家抽到的卡牌$k$,得到这一轮被淘汰的位置$c$. 可以知道 ...