NOIP提高组2018 D1T3 【赛道修建】
颓了好几天,终于把这到题处理了一下。
话说,其实我考场上想出正解了,但是手残,算复杂度的时候多按了一个零,导致算出来是1亿多的复杂度,都不敢打。。。就把部分分都捡了一下。。。
题目描述:
C 城将要举办一系列的赛车比赛。在比赛前,需要在城内修建 m 条赛道。
C 城一共有 n 个路口,这些路口编号为 1,2,…,n1,有 n−1 条适合于修建赛道的双向通行的道路,每条道路连接着两个路口。其中,第 ii 条道路连接的两个路口编号为 ai 和 bi,该道路的长度为 li。借助这 n-1n−1 条道路,从任何一个路口出发都能到达其他所有的路口。
一条赛道是一组互不相同的道路 e1,e2,…,ek满足可以从某个路口出发,依次经过 道路 e1,e2,…,ek(每条道路经过一次,不允许调头)到达另一个路口。一条赛道的长度等于经过的各道路的长度之和。为保证安全,要求每条道路至多被一条赛道经过。
目前赛道修建的方案尚未确定。你的任务是设计一种赛道修建的方案,使得修建的 m 条赛道中长度最小的赛道长度最大(即 m 条赛道中最短赛道的长度尽可能大)
思路分析:
从部分分开始讲吧。
菊花图:
这个部分分还是挺好拿的,把边从大到小排序之后,直接二分答案。两个指针,i,正着来,j,倒着来,i就顺着取下去,对于每个i给它匹配一个最大的相加刚好大于二分值的j(一开始就大于二分值的要特殊处理),注意到这个决策是有单调性的,即:当i1小于i2时,那么相匹配的j1一定大于等于j2,这样的话,我们每次只要扫一遍就能得到答案(考完后有人和我说求菊花图要log2二分答案套二分,嗯,就是我们的zyk同志,其实我一直都觉得这个人的脑回路特别清奇。。。)。
分支不超过3:
这个的话其实就是正解的简化版了,考虑二分答案加树形DP。
dp[u]:表示以u为根的子树中有多少长度大于mid的链。
f[u]:表示以u为根的子树中,除去那些被统计到dp数组中的链,现在能传到父亲的链的长度最长的链的长度(貌似有点拗口呢。。。)。
转移应该很简单了吧。
首先,dp[u]=∑v∈u's sons 如果u的两个儿子的最长链加起来大于mid,那么再给dp[u]+1,f[u]=0,否则的话,f[u]=max(f[v1],f[v2])。
正解:
正解其实就是把两者结合一下啦。
但是特别注意的就是:我们要在满足匹配数最大的情况下,找一条最长的链传给父亲。
那么这个要求我们应该怎么来实现呢?——二分嘛!
我们可以二分我们需要传上去的那条链,然后在匹配的时候跳过这条链就行了。(其实这是成一类dalao教我的)
代码实现:(没想到吧,我转C++辣!!!)
(不得不说一句——C++压行是真的爽,啊哈哈哈!!!)
#include <bits/stdc++.h>
using namespace std;
const int maxn=50005;
int dp[maxn],f[maxn],head[maxn],nxt[2*maxn],vet[2*maxn],dist[2*maxn];
int tot,mid;
void add(int x,int y,int z){
tot++;
nxt[tot]=head[x];
vet[tot]=y;
head[x]=tot;
dist[tot]=z;
}
bool cmp(int a,int b) {
return a>b;
}
void dfs(int u,int father){
vector<int> a;
for (int i=head[u];i;i=nxt[i]){
int v=vet[i];
if (v==father) continue;
dfs(v,u);
f[v]+=dist[i];
if (f[v]<mid) a.push_back(f[v]); else dp[u]++;
dp[u]+=dp[v];
}
int l=0,r=a.size()-1;
sort(a.begin(),a.end(),cmp);
a.push_back(0);
int ans=a.size()-1,Max=0,i=0,j=a.size()-2;
while (i<j) if (a[i]+a[j]>=mid) i++,j--,Max++; else j--;
while (l<=r){
int now=(l+r)>>1,res=0,i=0,j=a.size()-2;
while (i<j){
if (i==now) {i++; continue;}
if (j==now) {j--; continue;}
if (a[i]+a[j]>=mid) i++,j--,res++; else j--;
}
if (res>=Max) Max=res,ans=now,r=now-1; else l=now+1;
}
dp[u]+=Max; f[u]=a[ans];
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for (int i=1;i<n;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
int l=1,r=500000000,ans=0;
while (l<=r){
memset(dp,0,sizeof(dp));
memset(f,0,sizeof(f));
mid=(l+r)>>1;
dfs(1,0);
if (dp[1]>=m) ans=mid,l=mid+1; else r=mid-1;
}
printf("%d\n",ans);
return 0;
}
NOIP提高组2018 D1T3 【赛道修建】的更多相关文章
- noip 2018 D1T3 赛道修建
noip 2018 D1T3 赛道修建 首先考虑二分答案,这时需要的就是对于一个长度求出能在树中选出来的最多的路径条数.考虑到一条路径是由一条向上的路径与一条向下的路径构成,或者仅仅是向上或向下的路径 ...
- [NOIP提高组2018]货币系统
[TOC] 题目名称:货币系统 来源:2018年NOIP提高组 链接 博客链接 CSDN 洛谷博客 洛谷题解 题目链接 LibreOJ(2951) 洛谷(P5020) 大视野在线评测(1425) 题目 ...
- NOIP提高组2018试题解析 目录
重磅来袭! 本蒟蒻准备挑战一下NOIP2018提高组的试题啦(怎么办 我猜我连10分都拿不了) 目录: Day1 1.铺设道路 讲解 得分:100 2.货币系统 讲解 3.赛道修建 讲解 ...
- NOIP提高组2018试题解析 Day1 T1 铺设道路 P5019
题目描述 春春是一名道路工程师,负责铺设一条长度为 nn 的道路. 铺设道路的主要工作是填平下陷的地表.整段道路可以看作是 nn 块首尾相连的区域,一开始,第 ii 块区域下陷的深度为 d_idi ...
- 树型大融合——NOIP提高组2015 D1T3 【运输计划】
下午用一个小时看了一下树上差分,打了个差分模板,A了3题,真的爽! 题目描述: 公元2044 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 ...
- 2018.12.30【NOIP提高组】模拟赛C组总结
2018.12.30[NOIP提高组]模拟赛C组总结 今天成功回归开始做比赛 感觉十分良(zhōng)好(chà). 统计数字(count.pas/c/cpp) 字符串的展开(expand.pas/c ...
- 2018.12.08【NOIP提高组】模拟B组总结(未完成)
2018.12.08[NOIP提高组]模拟B组总结 diyiti 保留道路 进化序列 B diyiti Description 给定n 根直的木棍,要从中选出6 根木棍,满足:能用这6 根木棍拼出一个 ...
- NOIP提高组初赛难题总结
NOIP提高组初赛难题总结 注:笔者开始写本文章时noip初赛新题型还未公布,故会含有一些比较老的内容,敬请谅解. 约定: 若无特殊说明,本文中未知数均为整数 [表达式] 表示:在表达式成立时它的值为 ...
- NOIP提高组2004 合并果子题解
NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消 ...
随机推荐
- 目标识别AI资料
朋友推荐的, 还有自己搜的. 入门可以看看. 网上资料应该不少, 一搜一大把, 简单记下地址. Review of Deep Learning Algorithms for Object Detect ...
- 解决winserver2012R2安装VMware15(pro)问题
问题:之前就遇到过,一台WIN2012R2装不了vmwareworkstation15的问题.这次又安装了一台WindowsServer2012R2Datacenter:依然发现安装不了,于是开始上网 ...
- 分数运算(gcd)
时间限制 1000 ms 内存限制 32768 KB 代码长度限制 100 KB 判断程序 Standard (来自 小小) 题目描述 计算机中采用浮点数表示所有实数,但这意味着精度丢失.例如无法精确 ...
- 沉珂日重的Java项目 Spring真的帮到我们了吗?
开局三连图. 这是刚开始时的程序结构,虽清晰已经有混乱的前兆. 业务增加,人员增加后就会沉珂日重. 几年后,最后的模样会让使用者和维护者都很无奈. 人们喜欢把Java程序的层次结构比作建筑,实际却最像 ...
- ZT:通过Find命令找到你要找的东西
https://os.51cto.com/art/202003/612049.htm find 命令有巨多的选项可以帮助你准确定位你在 Linux 系统上需要寻找的文件.这篇文章讨论了一系列非常有用的 ...
- 转载:把你的精力专注在java,jvm原理,spring原理,mysql锁,事务,多线程,大并发,分布式架构,微服务,以及相关的项目管理等等,这样你的核心竞争力才会越来越高
https://developer.51cto.com/art/202001/608984.htm 把你的精力专注在java,jvm原理,spring原理,mysql锁,事务,多线程,大并发,分布式架 ...
- .NET实现可交互的WINDOWS服务(转载自CSDN"烈火蜓蜻")
Windows 服务应用程序在不同于登录用户的交互区域的窗口区域中运行.窗口区域是包含剪贴板.一组全局原子和一组桌面对象的安全对象.由于 Windows 服务的区域不是交互区域,因此 Windows ...
- 渣渣的Leetcode之旅(Python3)_1.两数之和
题目:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标.你可以假设每种输入只会对应一个答案.但是,数组中同一个元素不能使用两遍 ...
- python3 if
if-else python中特有if-elif-else语句
- Scala的lazy应用
如果将一个变量声明为lazy,则只有在第一次使用该变量时,变量对应的表达式才会起作用. 例如:对于特别耗时的的计算操作特别有用,如打开文件IO,网络IO等. import scala.io.Sourc ...