洛谷P2680 运输计划
大概就是二分+树上差分...
题意:给你树上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 运输计划的更多相关文章
- 洛谷 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运输计划
传送门啦 要求的就是,把树上的一条边的权值设为0之后,所有路径中的最大值的最小值. 首先二分最大值,假设某次二分的最大值为x,我们首先找出所有大于x的路径(也就是我们需要通过改权缩短的路径),并把路径 ...
随机推荐
- Flask-sqlalchemy 语法总结
Flask-sqlalchemy 语法总结 ** DDLdb.create_all() :创建实体表db.drop_all(): 删除表 1)插入表Db.session.add(user) #user ...
- Zabbix监控系统部署:前端初始化
1. 概述 在上一篇博客<Zabbix监控系统部署:源码安装.md>中,主要进行了zabbix最新版的源码编译安装. (博客园地址:https://www.cnblogs.com/liwa ...
- 探索guava(一)——前置条件Preconditions类
作用 可以简洁的完成参数检验,在进行业务逻辑代码前进行前置判断.并且避免了冗长的if语句.guava将所有检验的API都放置于Preconditions类中. API Preconditions类大致 ...
- Spring整合SpringMVC
整合:把在springMVC配置文件中的spring提取出来整合为另一份配置文件 希望: 1).Spring的配置文件只是用来配置和业务逻辑有关的功能(数据源.事务控制.切面....) 2).Spri ...
- shell脚本--数值计算
原生bash不支持简单的数学运算,即使是最简单的加减乘除 但是,可以使用$[]和expr来实现整数运算 如果要实现小数运算,可以使用bc命令 使用$[]来实现: #!/bin/bash #文件名:te ...
- 定义类型别名(typedef,using)
说到类型别名,无非是给类型名(如int,char,float,double,bool)取一个比较有特殊含义的名字而已 最常用的关键莫过于 typedef 吧 typedef最常见的用法是与结构体str ...
- Solution of wireless link "PCI unknown" on Centos 7.1
Pick From http://www.blogjava.net/miaoyachun/archive/2015/09/17/427366.html After Centos 7.1 tobe in ...
- jmeter作用域规则
创建测试计划时,会创建一个有序的一系列将要被执行的请求列表,这些请求通常被组织在有序的控制器下 一些控制器会影响包含在它下面的请求顺序 ,这些特殊的控制器可以参考这里:the component re ...
- js運算符
運算符算術運算符.邏輯運算符.賦值運算符.比較運算符.條件運算符 字符串的合併,用+,如果是字符串和數字用+連接,則當做字符串合併. 條件運算符:if(條件)?語句1,語句2:
- json_decode()相关报错
错误描述 PHP Warning: json_decode() expects parameter 1 to be string, array given in xxx.php on line 29 ...