洛谷P2680运输计划
传送门啦
要求的就是,把树上的一条边的权值设为0之后,所有路径中的最大值的最小值。
首先二分最大值,假设某次二分的最大值为x,我们首先找出所有大于x的路径(也就是我们需要通过改权缩短的路径),并把路径上的所有边都标记一下。
在标记完成后,枚举所有边,如果存在一条边位于所有长度大于于x的路径上,并且删除之后能使所有路径都满足 $ length<=x $ ,则返回 $ true $ ,否则 $ false $ 。
还有一个问题就是,对于某个路径,如何快速标记出他经过的所有边呢?我们可以使用差分,用树上前缀和来表示某个点被标记次数。比如某条边 $ E(u,v) $ ,先把 $ sum[u]+=1,sum[v]+=1 $ ,然后 $ sum[lca(u,v)]-=2 $
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define re register
using namespace std;
const int maxn = 300005;
inline int read(){
char ch = getchar();
int f = 1 , x = 0;
while(ch > '9' || ch < '0'){if(ch == '-') f = -1;ch = getchar();}
while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();}
return x * f;
}
int n,m,a,b,t,u[maxn],v[maxn];
int head[maxn],tot;
int f[maxn][21],ans;
struct Edge{
int from,to,val,next;
}edge[maxn << 1];
inline void add(int u , int v , int w){
edge[++tot].from = u;
edge[tot].to = v;
edge[tot].val = w;
edge[tot].next = head[u];
head[u] = tot;
}
int dep[maxn],dis[maxn],value[maxn],len[maxn];
int id[maxn],cnt;
inline void dfs(int x , int fa) {
id[++cnt] = x;
dep[x] = dep[fa] + 1;
f[x][0] = fa;
for(re int i = 1 ; (1 << i ) <= dep[x] ; ++i)
f[x][i] = f[f[x][i - 1]][i - 1];
for(re int i = head[x] ; i ; i = edge[i].next) {
int v = edge[i].to;
if(v == fa) continue;
dis[v] = dis[x] + edge[i].val;
value[v] = edge[i].val;
dfs(v , x);
}
}
inline int lca(int u , int v){
if(dep[u] < dep[v]) swap(u , v);
for(re int i = 18 ; i >= 0 ; --i)
if((1 << i) <= (dep[u] - dep[v]))
u = f[u][i];
if(u == v) return u;
for(re int i = 18 ; i >= 0 ; --i){
if((1 << i) <= dep[u] && f[u][i] != f[v][i]) {
u = f[u][i] ;
v = f[v][i] ;
}
}
return f[u][0];
}
int sum[maxn];
inline bool check(int k){
for(re int i = 1 ; i <= n ; ++i)
sum[i] = 0;
int maxx = 0 , cnt = 0 ;
for(re int i = 1 ; i <= m ; ++i) {
if(len[i] > k) {
maxx = max(maxx , len[i]) ;
cnt++;
sum[u[i]]++; sum[v[i]]++;
sum[lca(u[i] , v[i])] -= 2;
}
}
for(re int i = n ; i >= 0 ; i--)
sum[f[id[i]][0]] += sum[id[i]] ;
for(re int i = 1 ; i <= n ; ++i)
if(sum[i] >= cnt && maxx - value[i] <= k)
return true;
return false;
}
int main(){
n = read() ; m = read();
for(re int i = 1 ; i <= n - 1 ; ++i){
a = read(); b = read(); t = read();
add(a , b , t);
add(b , a , t);
}
dfs(1 , 0);
int l = 0 , r = 0 ;
for(re int i = 1 ; i <= m ; ++i){
u[i] = read(); v[i] = read();
len[i] = dis[u[i]] + dis[v[i]] - 2 * dis[lca(u[i] , v[i])] ;
r = max(r , len[i]);
}
while(l <= r) {
int mid = (l + r) >> 1;
if(check(mid)) {
ans = mid;
r = mid - 1 ;
}
else l = mid + 1;
}
printf("%d\n",ans);
return 0;
}
洛谷P2680运输计划的更多相关文章
- 洛谷 P2680 运输计划-二分+树上差分(边权覆盖)
P2680 运输计划 题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条 ...
- 洛谷 P2680 运输计划 解题报告
P2680 运输计划 题目背景 公元2044年,人类进入了宇宙纪元. 题目描述 公元2044年,人类进入了宇宙纪元. \(L\)国有\(n\)个星球,还有\(n-1\)条双向航道,每条航道建立在两个星 ...
- [NOIP2015] 提高组 洛谷P2680 运输计划
题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...
- 洛谷P2680 运输计划 [LCA,树上差分,二分答案]
题目传送门 运输计划 Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n?1 条双向航道,每条航道建立在两个星球之间, 这 n?1 条航道连通了 L 国的所 ...
- 洛谷 P2680 运输计划(NOIP2015提高组)(BZOJ4326)
题目背景 公元 \(2044\) 年,人类进入了宇宙纪元. 题目描述 公元\(2044\) 年,人类进入了宇宙纪元. L 国有 \(n\) 个星球,还有 \(n-1\) 条双向航道,每条航道建立在两个 ...
- 洛谷 P2680 运输计划
题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...
- 洛谷——P2680 运输计划
https://www.luogu.org/problem/show?pid=2680 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每 ...
- 洛谷P2680 运输计划——树上差分
题目:https://www.luogu.org/problemnew/show/P2680 久违地1A了好高兴啊! 首先,要最大值最小,很容易想到二分: 判断当前的 mid 是否可行,需要看看有没有 ...
- 洛谷P2680 运输计划
大概就是二分+树上差分... 题意:给你树上m条路径,你要把一条边权变为0,使最长的路径最短. 最大的最小,看出二分(事实上我并没有看出来...) 然后二分k,对于所有大于k的边,树上差分求出最长公共 ...
随机推荐
- Mac上安装python3并设置SublimeREPL插件默认运行python3
1.安装python3 $ brew search python $ brew install python3 这里安装完后不需要单独添加环境变量,程序已经处理好,可以直接运行python3命令. $ ...
- List of NP-complete problems
This is a list of some of the more commonly known problems that are NP-complete when expressed as de ...
- 关于2-SAT
其实以前写过关于$2-SAT$的,但是那时的自己太懵懂了. 这是以前写过的文章link 关于$2-SAT$,其实就想说两件事情. $2-SAT$边建立的逻辑 $2-SAT$边建立的逻辑是必须关系,若$ ...
- for,while,do while
long i; ;i<;i++) printf( printf("%ld\n",i); ) printf("b\n"); i=; do { printf( ...
- ribbion的负载均衡之端口的切换
可以说在这里被坑了很久,终于今天在大神的指导下,成功实现了负载均衡,切换不同的端口,这里来记录下,首先来看下效果图吧: 到底是怎么实现的呢?到底是如何切换的呢? 具体来讲: 几个步骤,启动服务注册中心 ...
- python基础之函数进阶之函数作为返回值/装饰器
因为装饰器需要用到返回函数的知识,所以在这里将返回函数和装饰器合并讲解. 什么是返回函数? 我们知道,一个函数中return可以返回一个或者多个值,但其实,return不仅可以返回值,还可以返回函数. ...
- go语言从零学起(二)--list循环删除元素(转载)
本篇系转载 在使用go的container/list的package时,你可能会无意间踩一个小坑,那就是list的循环删除元素. list删除元素,直观写下来的代码如下: package main i ...
- Hadoop生态圈-HBase性能优化
Hadoop生态圈-HBase性能优化 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.
- 关于JSON的解析方式
借鉴:站在巨人的肩膀上 一.json-lib json-lib最开始的也是应用最广泛的json解析工具,json-lib 不好的地方确实是依赖于很多第三方包,在Json.org网站上,Java可以使用 ...
- np.isin判断数组元素在另一数组中是否存在
np.isin用法 觉得有用的话,欢迎一起讨论相互学习~Follow Me np.isin(a,b) 用于判定a中的元素在b中是否出现过,如果出现过返回True,否则返回False,最终结果为一个形状 ...