大概就是二分+树上差分...

题意:给你树上m条路径,你要把一条边权变为0,使最长的路径最短。

最大的最小,看出二分(事实上我并没有看出来...)

然后二分k,对于所有大于k的边,树上差分求出最长公共边,然后看是否可以。

(yy的解法②:边按照长度排序,然后二分。删除最长公共边。据logeadd juru说是三分)

代码量3.6k,180行,还是有点长的。

 #include <cstdio>
#include <algorithm>
#include <cstring>
const int N = ; inline void read(int &x) {
char c = getchar();
x = ;
while(c > '' || c < '') {
c = getchar();
}
while(c <= '' && c >= '') {
x = (x << ) + (x << ) + c - ;
c = getchar();
}
return;
} struct Edge {
int v, nex, len;
}edge[N << ]; int top; int e[N], n, m, lm, fa[N][], d[N], lenth[N]; /// 点
int l[N], r[N], mid[N], len[N]; /// 路径
bool use[N]; /// 树上差分
int num, large, R, f[N]; inline void add(int x, int y, int z) {
edge[++top].v = y;
edge[top].len = z;
edge[top].nex = e[x];
e[x] = top;
return;
} inline void DFS1(int x, int f) {
fa[x][] = f;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y != f) {
lenth[y] = lenth[x] + edge[i].len;
d[y] = d[x] + ;
DFS1(y, x);
}
}
return;
} inline void getlca() {
while(( << lm) < n) {
lm++;
}
DFS1(, );
for(int i = ; i <= lm; i++) {
for(int x = ; x <= n; x++) {
fa[x][i] = fa[fa[x][i - ]][i - ];
}
}
return;
} inline int lca(int x, int y) {
if(d[x] > d[y]) {
std::swap(x, y);
}
int t = lm;
while(t > - && d[y] > d[x]) {
if(d[fa[y][t]] >= d[x]) {
y = fa[y][t];
}
t--;
}
if(x == y) {
return x;
}
t = lm;
while(t > - && fa[x][] != fa[y][]) {
if(fa[x][t] != fa[y][t]) {
x = fa[x][t];
y = fa[y][t];
}
t--;
}
return fa[x][];
} inline int DFS(int x) {
int cnt = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == fa[x][]) {
continue;
}
int temp = DFS(y);
cnt += temp;
if(temp == num) {
large = std::max(large, edge[i].len);
}
}
cnt += f[x];
return cnt;
} inline bool check(int k) {
num = ;
memset(f, , sizeof(f));
for(int i = ; i <= m; i++) {
bool t = len[i] > k;
use[i] = t;
num += t;
if(t) {
f[l[i]]++;
f[r[i]]++;
f[mid[i]] -= ;
}
}
large = ;
DFS();
return R - large <= k;
} inline int getlong(int i) {
int x = l[i];
int ans = ;
while(x != mid[i]) {
ans = std::max(ans, lenth[x] - lenth[fa[x][]]);
x = fa[x][];
}
x = r[i];
while(x != mid[i]) {
ans = std::max(ans, lenth[x] - lenth[fa[x][]]);
x = fa[x][];
}
return ans;
} int main() {
scanf("%d%d", &n, &m);
int x, y, z;
for(int i = ; i < n; i++) {
//scanf("%d%d%d", &x, &y, &z);
read(x);
read(y);
read(z);
add(x, y, z);
add(y, x, z);
}
getlca();
int dr = , dl = , dm, A = ;
for(int i = ; i <= m; i++) {
//scanf("%d%d", &l[i], &r[i]);
read(l[i]);
read(r[i]);
mid[i] = lca(l[i], r[i]);
len[i] = lenth[l[i]] + lenth[r[i]] - * lenth[mid[i]];
if(len[i] > dr) {
dr = len[i];
A = i;
}
}
R = dr;
dl = dr - getlong(A);
if(dl < ) {
printf("ERROR ");
}
while(dl < dr) {
dm = (dr + dl) / ;
if(check(dm)) {
//printf("check %d 1 \n", dm);
dr = dm;
}
else {
//printf("check %d 0 \n", dm);
dl = dm + ;
}
}
printf("%d", dr);
return ;
}

AC代码

洛谷P2680 运输计划的更多相关文章

  1. 洛谷 P2680 运输计划-二分+树上差分(边权覆盖)

    P2680 运输计划 题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条 ...

  2. 洛谷 P2680 运输计划 解题报告

    P2680 运输计划 题目背景 公元2044年,人类进入了宇宙纪元. 题目描述 公元2044年,人类进入了宇宙纪元. \(L\)国有\(n\)个星球,还有\(n-1\)条双向航道,每条航道建立在两个星 ...

  3. [NOIP2015] 提高组 洛谷P2680 运输计划

    题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...

  4. 洛谷P2680 运输计划 [LCA,树上差分,二分答案]

    题目传送门 运输计划 Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n?1 条双向航道,每条航道建立在两个星球之间, 这 n?1 条航道连通了 L 国的所 ...

  5. 洛谷 P2680 运输计划(NOIP2015提高组)(BZOJ4326)

    题目背景 公元 \(2044\) 年,人类进入了宇宙纪元. 题目描述 公元\(2044\) 年,人类进入了宇宙纪元. L 国有 \(n\) 个星球,还有 \(n-1\) 条双向航道,每条航道建立在两个 ...

  6. 洛谷 P2680 运输计划

    题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...

  7. 洛谷——P2680 运输计划

    https://www.luogu.org/problem/show?pid=2680 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每 ...

  8. 洛谷P2680 运输计划——树上差分

    题目:https://www.luogu.org/problemnew/show/P2680 久违地1A了好高兴啊! 首先,要最大值最小,很容易想到二分: 判断当前的 mid 是否可行,需要看看有没有 ...

  9. 洛谷P2680运输计划

    传送门啦 要求的就是,把树上的一条边的权值设为0之后,所有路径中的最大值的最小值. 首先二分最大值,假设某次二分的最大值为x,我们首先找出所有大于x的路径(也就是我们需要通过改权缩短的路径),并把路径 ...

随机推荐

  1. Elasticsearch学习总结 (Centos7下Elasticsearch集群部署记录)

    一.  ElasticSearch简单介绍 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticse ...

  2. 《Linux内核分析》第七周笔记 可执行程序的装载

    20135132陈雨鑫 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000  ...

  3. LINUX内核分析第八周总结:进程的切换和系统的一般执行过程

    一.进程调度与进程切换 1.不同的进程有不同的调度需求 第一种分类: I/O密集型(I/O-bound) 频繁的进行I/O 通常会花费很多时间等待I/O操作的完成 CPU密集型(CPU-bound) ...

  4. android 活动的生命周期

    掌握活动的生命周期非常重要,因为一个正常的android应用,会有很多的活动,如何在这些活动之间进行切换.数据的交互等,就经常会用到活动的生命周期这一块的知识.可以说,只要掌握了活动的生命周期,才能更 ...

  5. PAT 1049 数列的片段和

    https://pintia.cn/problem-sets/994805260223102976/problems/994805275792359424 给定一个正数数列,我们可以从中截取任意的连续 ...

  6. Docker中安装Nexus3

    https://blog.csdn.net/sqandczm/article/details/78560710 https://hub.docker.com/r/sonatype/nexus/ htt ...

  7. solt插槽的使用。

    在组件内template中使用 <slot name='header'></slot> 在页面内 直接添加标签 如 <hs><h1 slot='header' ...

  8. Cmder 常用配置

    windows 系统的 cmd 命令窗口不是很好用,可以试试 Cmder 工具包. 1.在运行框中快速启动 Cmder 将 cmder.exe 文件所在目录加载环境变量 PATH 中. 2.把 cms ...

  9. parent()、parents()和parentsUntil()的区别

    1.parent() 返回被选元素的直接父元素,该方法只会向上一级对 DOM 树进行遍历: 2.parents() 返回被选元素的所有祖先元素,它一路向上直到文档的根元素 (<html>) ...

  10. js邏輯

    js的邏輯對象可以用於將非邏輯對象轉換為邏輯 var a=new Boolean(); a為false的幾種情況,0,-0,null,false,“”,undefined,NAN