洛谷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 掌管一家 ...
随机推荐
- XFire搭建WebService和客户端访问程序
开发环境:myeclipse8.6+jdk1.6.0_29+tomcat6.0.37 JAX-WS搭建webservice:http://www.cnblogs.com/gavinYang/p/352 ...
- Eclipse 重构功能的使用与重构快捷键
重构是什么? 在代码写好之后改进它的设计. 重构分类:物理结构.类层次结构.类内部结构. 名称 快捷键 直译 作用范围 描述 Rename Alt + Shift + R 可以对任意变量.类. ...
- 几何+思维 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest K. Revenge of the Dragon
题目链接:http://codeforces.com/gym/101149/problem/K 题目大意: 给你两个点a,b.一个人在a点,一个人在b点,b点的人要追杀a的点,他的跑步速度是a的两倍. ...
- HDU 4990 Reading comprehension 简单矩阵快速幂
Problem Description Read the program below carefully then answer the question.#pragma comment(linker ...
- vim如何粘贴
刚开始vim的学习之旅,在进行粘贴操作时遇到了麻烦. 教程上粘贴的命令是p,但我发现该命令只适用于从vim到vim的复制(p未必就仅仅局限于此,但我目前所了解到的情况如此),当我从网上复制了一段代码想 ...
- css table-border
1.table上设边框,td上设边框: <style> table{border-right:1px solid #F00;border-bottom:1px solid #F00} ta ...
- DELPHI中的快捷方式一览(完全版)
1.SHIFT+鼠标左键 先选中任一控件,按键后可选中窗体(选中控件后按Esc效果一样)2.Shift+F8 调试时弹出CPU窗口.3.Shift+F10 等于 ...
- 用java代码调用shell脚本执行sqoop将hive表中数据导出到mysql
1:创建shell脚本 touch sqoop_options.sh chmod 777 sqoop_options.sh 编辑文件 特地将执行map的个数设置为变量 测试 可以java代码传参数 ...
- [POJ 2559]Largest Rectangle in a Histogram 题解(单调栈)
[POJ 2559]Largest Rectangle in a Histogram Description A histogram is a polygon composed of a sequen ...
- DAY1-GO初识(概述)
一.概述 1.特征 1.1.语法简单:规则严谨.保留指针.但默认阻止指针运算.将切片和字典作为内置类型.更好的维护性: 1.2.并发模型:运行时用GOroutine,一个关键字.简单而自然:搭配cha ...