洛谷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 掌管一家 ...
随机推荐
- Vue.js基础 笔记
Vue.js的声明: < script src = “https://unpkg.com/vue” ></ script > el:值可以是CSS选择符.HTML元素.或者是返 ...
- MySql 插入数据库报错 Incorrect string value: '\xF0\xA0\x86\xA2'
今天从nginx日志分析搜索关键字,然后把关键字插入到Mysql数据库里,出现如下错误 SQL state [HY000]; error code [1366]; Incorrect string v ...
- nginx 初探 之反向代理
首先要解释的是什么叫做反向代理? 平时我们浏览网页可以输入网址直接访问, 但如果访问国外的网站, 可能就没那么简单('中国特色'), 这时候我们需要配置一个代理服务器, 然后通过此服务器中转来访 ...
- linux下开放端口
/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT 将该设置添加到防火墙的规则中 /etc/rc.d/init.d/iptables save
- Codeforces Round #191 (Div. 2) B. Hungry Sequence(素数筛选法)
. Hungry Sequence time limit per test 1 second memory limit per test 256 megabytes input standard in ...
- JVM调优总结(4):分代垃圾回收
为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象, ...
- JVM调优总结(3):垃圾回收面临的问题
如何区分垃圾 上面说到的“引用计数”法,通过统计控制生成对象和删除对象时的引用数来判断.垃圾回收程序收集计数为0的对象即可.但是这种方法无法解决循环引用.所以,后来实现的垃圾判断算法中,都是从程序运行 ...
- struts的标签
<%@ taglib uri="/struts-tags" prefix="s"%> <%@ taglib uri="/WEB-IN ...
- python之supervisor进程管理工具
supervisor是python写的一个管理进程运行的工具,可以很方便的监听.启动.停止.重启一个或多个进程:有了supervisor后,就不用字节写启动和监听的shell脚本了,非常方便. sup ...
- 解决su – 后显示-bash-4.1#
<1>现象 设置tfs的管理用户时. su - admin时,出现 -bash-4.1# <2>解决 chown admin:admin /home/admin ...