树型大融合——NOIP提高组2015 D1T3 【运输计划】
下午用一个小时看了一下树上差分,打了个差分模板,A了3题,真的爽!
题目描述:
公元2044 年,人类进入了宇宙纪元。
L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球。
小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道是需要时间的,对于航道j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之间不会产生任何干扰。
为了鼓励科技创新, L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。
在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后,这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的物流公司的阶段性工作就完成了。
如果小 P 可以自由选择将哪一条航道改造成虫洞, 试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?
数据范围:
n<=300000,m<=300000
思路分析:
首先得写个倍增求LCA求个链长,这应该没问题吧,我之前讲过的(不懂戳这里,你们可能会惊奇地发现下面的代码里我的lca是复的,嘘——)。
那么再看问题,“使最大的运输时间最少”——某王 定理之二十一(滑稽):任何求最大值最小,最小值最大的问题十有八九是二分答案。
嗯,很好,让我们考虑二分答案这种神奇的东西。
对于我们二分出的答案mid,我们应该怎么来判断它是否合法呢?
首先让我们找出这m条链中长度大于mid的,求出链的数量num以及最长链的长度len。
显然,当这num条边中都经过一条长度至少为(len-mid)的边,那么当我们删去这条边后,这个答案就是合法的,因为原本所有长度大于mid的链长度都会小于等于mid。
那么我们应该怎么找这num条链都经过的边呢?——树上差分嘛,没有争议的(不懂的话戳这里)。
代码实现:
var
f:array[0..300000,0..20]of longint;
vis:array[0..300000]of boolean;
next,vet,dist:array[0..600000]of longint;
head,cnt,depth,g,d,len,u,v,grand:array[0..300000]of longint;
ans,i,j,n,m,tot,x,y,z,max,num,k,l,r,mid:longint;
flag:boolean;
procedure add(x,y,z:longint);
begin
inc(tot);
next[tot]:=head[x];
vet[tot]:=y;
head[x]:=tot;
dist[tot]:=z;
end;
procedure dfs(u,dep,dis:longint);
var
i,v:longint;
begin
depth[u]:=dep; vis[u]:=true;
for i:=1 to 20 do
f[u,i]:=f[f[u,i-1],i-1];
i:=head[u];
while i<>0 do
begin
v:=vet[i];
if not vis[v] then
begin
f[v,0]:=u;
d[v]:=dis+dist[i];
dfs(v,dep+1,d[v]);
end;
i:=next[i];
end;
end;
function lca(a,b:longint):longint;
var
i,t:longint;
begin
if depth[a]>depth[b] then begin t:=a; a:=b; b:=t; end;
for i:=20 downto 0 do
if depth[f[b,i]]>=depth[a] then b:=f[b,i];
if a=b then exit(a);
for i:=20 downto 0 do
if f[a,i]<>f[b,i] then
begin a:=f[a,i]; b:=f[b,i]; end;
exit(f[a,0]);
end;
procedure getans(u,father:longint);
var
i,v:longint;
begin
g[u]:=cnt[u];
i:=head[u];
while i<>0 do
begin
v:=vet[i];
if v<>father then
begin
getans(v,u);
g[u]:=g[u]+g[v];
if (g[v]=num)and(dist[i]>=k) then flag:=true;
end;
i:=next[i];
end;
end;
function check(x:longint):boolean;
var
i:longint;
begin
flag:=false; max:=0; num:=0;
fillchar(g,sizeof(g),0);
fillchar(cnt,sizeof(cnt),0);
for i:=1 to m do
if len[i]>x then
begin
inc(cnt[u[i]]); inc(cnt[v[i]]);
cnt[grand[i]]:=cnt[grand[i]]-2;
inc(num);
if len[i]>max then max:=len[i];
end;
k:=max-x;
getans(1,0);
exit(flag);
end;
begin
read(n,m);
for i:=1 to n-1 do
begin
read(x,y,z);
add(x,y,z); add(y,x,z);
end;
dfs(1,1,0);
for i:=1 to m do
begin
read(u[i],v[i]);
grand[i]:=lca(u[i],v[i]);
len[i]:=d[u[i]]+d[v[i]]-2*d[grand[i]]; //有没有觉得我今天的码风格外清新,嗯,我用Guide写的代码。
if len[i]>max then max:=len[i];
end;
l:=1; r:=max;
while l<=r do
begin
mid:=(l+r)div 2;
if check(mid) then begin r:=mid-1; ans:=mid; end else l:=mid+1;
end;
writeln(ans);
end.
树型大融合——NOIP提高组2015 D1T3 【运输计划】的更多相关文章
- 题解——洛谷 P2680 NOIP提高组 2015 运输计划
树上差分加上二分答案 详细题解待填坑 #include <cstdio> #include <algorithm> #include <cstring> using ...
- 题解 【luogu P2680 NOIp提高组2015 运输计划】
题目链接 题解 题意 一棵树上有\(m\)条路径,可以将其中一条边的权值改为0,问最长的路径最短是多少 分析 最短的路径最长自然想到二分最长路径,设其为\(dis\) 关键在于如何check chec ...
- NOIP提高组 2013货车运输
觉得题目水的离开 不屑的大佬请离开 不会图论的请离开 ……. 感谢您贡献的访问量 ————————————华丽的分割线———————————— 题面: 题目描述 A 国有 n 座城市,编号从 1 到 ...
- NOIP提高组2018 D1T3 【赛道修建】
颓了好几天,终于把这到题处理了一下. 话说,其实我考场上想出正解了,但是手残,算复杂度的时候多按了一个零,导致算出来是1亿多的复杂度,都不敢打...就把部分分都捡了一下... 题目描述: C 城将要举 ...
- 题解 【luoguP1967 NOIp提高组2013 货车运输】
题目链接 题解 题意 给你一个无向图,求两个点之间的一条路径,使路径上的最小值最大 算法:Kruskal最大生成树+倍增lca 分析 首先容易知道,答案一定在该图的最大生成树上 之后问题便转换成了树上 ...
- NOIP提高组初赛难题总结
NOIP提高组初赛难题总结 注:笔者开始写本文章时noip初赛新题型还未公布,故会含有一些比较老的内容,敬请谅解. 约定: 若无特殊说明,本文中未知数均为整数 [表达式] 表示:在表达式成立时它的值为 ...
- NOIP提高组2004 合并果子题解
NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消 ...
- 计蒜客 NOIP 提高组模拟竞赛第一试 补记
计蒜客 NOIP 提高组模拟竞赛第一试 补记 A. 广场车神 题目大意: 一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n, ...
- [NOIP提高组2018]货币系统
[TOC] 题目名称:货币系统 来源:2018年NOIP提高组 链接 博客链接 CSDN 洛谷博客 洛谷题解 题目链接 LibreOJ(2951) 洛谷(P5020) 大视野在线评测(1425) 题目 ...
随机推荐
- laravel5Eloquent模型与数据表的创建
下面是有关管理员模型与表的创建 生成模型时同时生成数据库迁移文件 在生成的迁移文件中添加字段 运行命令行生成数据表 命令进行混合运用 生成工厂文件,数据填充文件 工厂模型代码 数据填充文件代码 数据填 ...
- mysql创建事务,分批次刷新大数据
对于需要刷新的大数据量,当一次刷新数据量过大时,事务太大,会导致binLog文件太大,在不同的数据库同步时,可能遇到问题,先整理如下,分批次刷新数据 DELIMITER // # 设置//为结束符,否 ...
- C++——大小写转换
代码如下: #include <iostream> using namespace std; int main() { char ch; cin>>ch; if(ch>' ...
- 8成以上的java线程状态图都画错了,看看这个-图解java并发第二篇
本文作为图解java并发编程的第二篇,前一篇访问地址如下所示: 图解进程线程.互斥锁与信号量-看完还不懂你来打我 图形说明 在开始想写这篇文章之前,我去网上搜索了很多关于线程状态转换的图,我惊讶的发现 ...
- Java多线程--两个线程同时对一个人的年龄进行增加和修改
public class Thread_A extends Thread { Human human; public Thread_A(String name, Human human) { supe ...
- 什么是Lambda架构
一.Lambda架构需求 Lambda架构背后的需求是由于MR架构的延迟问题.MR虽然实现了分布式.可扩展数据处理系统的目的,但是在处理数据时延迟比较严重.实际上如果内存和CPU足够强大,MR也可以实 ...
- Noip2017 Day2 T1 奶酪
题目描述 现有一块大奶酪,它的高度为 h,它的长度和宽度我们可以认为是无限大的,奶酪中间有许多半径相同的球形空洞.我们可以在这块奶酪中建立空间坐标系,在坐标系中,奶酪的下表面为z =0,奶酪的上表面为 ...
- js中的鼠标滚轮事件
## 事件对象 event 1 event事件对象,表示用来获取事件的详细信息,比如得到鼠标的横坐标:事件对象.clientX(clientX是可视区坐标) window.onclick = func ...
- node 进阶 | 通过node中如何捕获异常阐述express的特点
node如何捕获异常 node基于js的单线程,有了非阻塞异步回调的概念,但是在处理多个并发连接时,并发环境要求高,最重要的是单线程,单核CPU,一个进程crash则web服务都crash,但是为什么 ...
- Docker之使用Dockerfile创建定制化镜像(四)
Dockerfile简介 镜像的定制实际上就是定制每一层所添加的配置.文件.如果我们可以把每一层修改.安装.构建.操作的命令都写入一个脚本,用这个脚本来构建.定制镜像,那么哪些无法重复的问题.镜像构建 ...