洛谷P2680 运输计划 [LCA,树上差分,二分答案]
运输计划
Description
Input
Output
输出文件只包含一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。
Sample Input
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5
Sample Output
11
将第 1 条航道改造成虫洞: 则三个计划耗时分别为:11,12,11,故需要花费的时间为 12。
将第 2 条航道改造成虫洞: 则三个计划耗时分别为:7,15,11,故需要花费的时间为 15。
将第 3 条航道改造成虫洞: 则三个计划耗时分别为:4,8,11,故需要花费的时间为 11。
将第 4 条航道改造成虫洞: 则三个计划耗时分别为:11,15,5,故需要花费的时间为 15。
将第 5 条航道改造成虫洞: 则三个计划耗时分别为:11,10,6,故需要花费的时间为 11。
故将第 3 条或第 5 条航道改造成虫洞均可使得完成阶段性工作的耗时最短,需要花费的时间为 11。
分析:
一道$LCA$+二分的码农题。
不难看出,一定是需要求$LCA$来求两点的路径的。但是我们怎么处理减去一条边呢?
如果是暴力枚举每一条边,复杂度是$O(nm\log (n))$的,不过也能拿$60$分了。
考虑优化,题目要求的东西其实就是最长航线的最短时间,那么显然是二分答案。我们二分航线所需的最长时间,然后我们统计哪些航线的时间大于当前的$mid$值,然后$O(n)$搜索找出被所有大于$mid$的航线经过的边的最大值,然后用最长航线时间减去这个最大值,如果仍大于$mid$则不合法,否则就可以更行答案然后继续。
这里博主用的是倍增求$LCA$,另外这题数据较大,二分的时候需要控制边界,把二分的范围缩小一些。
Code:
//It is made by HolseLee on 21st Sep 2018
//Noip2015 D2T3
#include<cstdio>
#include<algorithm>
#define N 300020
#define Max(a,b) (a)>(b)?(a):(b)
using namespace std; int head[N],dep[N],sum[N],f[N][],ch[N],u[N],v[N],lca[N],dg[N],len[N];
int n,m,cnte,ans,root,maxx,cnt,maxe,maxdis;
struct Edge {
int to,val,nxt;
Edge() {}
Edge(const int &_x,const int &_y,const int &_z): to(_x),val(_y),nxt(_z) {}
}e[N<<]; inline int read()
{
char ch=getchar(); int num=;
while( ch<'' || ch>'' ) ch=getchar();
while( ch>='' && ch<='' ) {
num=(num<<)+(num<<)+(ch^); ch=getchar();
}
return num;
} void print(int x)
{
if( x> ) print(x/);
putchar(x%+'');
} inline void add(int x,int y,int z)
{
e[++cnte]=Edge(y,z,head[x]);
head[x]=cnte;
} void ready(int x,int fa)
{
dep[x]=dep[fa]+; f[x][]=fa;
for(int i=head[x]; i; i=e[i].nxt) {
int y=e[i].to;
if( y==fa ) continue;
sum[y]=sum[x]+e[i].val;
ready(y,x);
}
} void init()
{
for(int j=; j<=; ++j)
for(int i=; i<=n; ++i)
f[i][j]=f[f[i][j-]][j-];
} inline int LCA(int x,int y)
{
if( dep[x]<dep[y] ) x^=y^=x^=y;
for(int i=; i>=; --i)
if( f[x][i]==y ) return y;
else if( dep[f[x][i]]>=dep[y] ) x=f[x][i];
if( x==y ) return x;
for(int i=; i>=; --i)
if( f[x][i]!=f[y][i] ) x=f[x][i],y=f[y][i];
return f[x][];
} void dfs(int x)
{
for(int i=head[x]; i; i=e[i].nxt) {
int y=e[i].to;
if( y==f[x][] ) continue;
dfs(y);
ch[x]+=ch[y];
}
if( ch[x]==cnt && maxx<(sum[x]-sum[f[x][]]) )
maxx=sum[x]-sum[f[x][]];
} inline bool check(int x)
{
for(int i=; i<=n; ++i)ch[i]=;
cnt=; maxx=;
for(int i=; i<=m; ++i)
if( len[i]>x ) {
ch[u[i]]++, ch[v[i]]++;
ch[lca[i]]-=; cnt++;
}
dfs(root);
if( maxdis-maxx>x ) return false;
return true;
} int main()
{
n=read(), m=read();
int x,y,z;
for(int i=; i<n; ++i) {
x=read(), y=read(), z=read();
add(x,y,z), add(y,x,z);
dg[x]++, dg[y]++;
if( dg[x]>dg[root] ) root=x;
if( dg[y]>dg[root] ) root=y;
maxe=Max(maxe,z);
}
ready(root,); init();
for(int i=; i<=m; ++i) {
x=read(), y=read();
u[i]=x, v[i]=y, lca[i]=LCA(x,y);
len[i]=sum[x]+sum[y]-(sum[lca[i]]<<);
maxdis=Max(maxdis,len[i]);
}
int l=maxdis-maxe, r=maxdis, mid;
while( l<=r ) {
mid=(l+r)>>;
if( check(mid) ) r=mid-, ans=mid;
else l=mid+;
}
print(ans);
return ;
}
洛谷P2680 运输计划 [LCA,树上差分,二分答案]的更多相关文章
- 洛谷P2680 运输计划(树上差分+二分)
传送门 考虑树上乱搞 首先这是满足二分性质的,如果在某个时间可以完成工作那么比他更长的时间肯定也能完成工作 然后考虑二分,设当前答案为$mid$,如果有一条链的长度大于$mid$,那么这条链上必须得删 ...
- 【Luogu】P2680运输计划(树上差分+二分)
题目链接 总体思路……怎么说呢……是个暴力吧…… 首先用倍增预处理出每条路径的长度. 然后按长度把路径排序. 然后二分答案.对于当前答案mid检验,怎么检验呢? 首先差分把所有长度比mid大的链上除了 ...
- 洛谷 P2680 运输计划-二分+树上差分(边权覆盖)
P2680 运输计划 题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条 ...
- 洛谷 P2680 运输计划 解题报告
P2680 运输计划 题目背景 公元2044年,人类进入了宇宙纪元. 题目描述 公元2044年,人类进入了宇宙纪元. \(L\)国有\(n\)个星球,还有\(n-1\)条双向航道,每条航道建立在两个星 ...
- 洛谷P2680 运输计划(倍增LCA + 树上差分 + 二分答案)
[题目链接] [思路]: 根据题意可以明显看出,当所有任务都完成时的时间是最终的结果,也就是说本题要求,求出最小的最大值. 那这样的话就暗示了将答案二分,进行check. [check方法]: 如果说 ...
- 洛谷P2680 运输计划——树上差分
题目:https://www.luogu.org/problemnew/show/P2680 久违地1A了好高兴啊! 首先,要最大值最小,很容易想到二分: 判断当前的 mid 是否可行,需要看看有没有 ...
- 洛谷 P2680 运输计划(NOIP2015提高组)(BZOJ4326)
题目背景 公元 \(2044\) 年,人类进入了宇宙纪元. 题目描述 公元\(2044\) 年,人类进入了宇宙纪元. L 国有 \(n\) 个星球,还有 \(n-1\) 条双向航道,每条航道建立在两个 ...
- 洛谷——P2680 运输计划
https://www.luogu.org/problem/show?pid=2680 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每 ...
- [NOIP2015] 提高组 洛谷P2680 运输计划
题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...
随机推荐
- SpringCloud学习(2)——Rest微服务案例
创建父工程: microservicecloud 创建公共模块api:microservicecloudapi SQL脚本: 此学习路线总共创建3个库, 分别为clouddb01, clouddb0 ...
- Lucene 索引与检索架构图
- GridControl详解(九)表格中的控件
选择完成控件后,可用+号点开ColumnEdit列,改控件的类型是RepositoryItem类型的,其相应的属性和相应的控件属性是类似的 构建数据如下: DataTable dt = new Dat ...
- NYOJ 163 Phone List (字符串处理 字典树)
题目链接 描述 Given a list of phone numbers, determine if it is consistent in the sense that no number is ...
- JavaScript 判断手机端访问并跳转 redirect mobile
假如你的手机端网站在 /m 目录下 (function(a,b){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer| ...
- python并发编程之asyncio协程(三)
协程实现了在单线程下的并发,每个协程共享线程的几乎所有的资源,除了协程自己私有的上下文栈:协程的切换属于程序级别的切换,对于操作系统来说是无感知的,因此切换速度更快.开销更小.效率更高,在有多IO操作 ...
- 【swupdate文档 五】从可信的来源更新镜像
从可信的来源更新镜像 现在越来越重要的是,设备不仅要能安全地进行更新操作, 而且要能够验证发送的图像是否来自一个已知的源, 并且没有嵌入恶意软件. 为了实现这个目标,SWUpdate必须验证传入的镜像 ...
- 如何读懂statspack报告
前言:这篇文章是我从网上找到的,但可惜不知道是哪位大侠写(译)的,因此这里无法注明了.仔细看了看,这篇文章对初学者应该很有帮助,写的比较详细,通俗易懂,因此整理一下,便于阅读:内容略有调整,不单做调整 ...
- 用C++写程序的一些感悟
前言 近期使用C++有了一些心得很感悟,这里整理一下. 心得1 如果只会使用LabVIEW写程序,还想要进一步深入程序设计,一定要学习一门文本语言. 什么是会用LabVIEW 会用是个比较笼统的概念. ...
- angular中使用AMEXIO
1.用NPM添加依赖到项目中,amexio需要先添加以下四个依赖到项目 npm install jquery@3.2.1 --save npm install bootstrap@4.0.0-alp ...