NOIP2015运输计划(树上前缀和+LCA+二分)
Description
公元 2044 年,人类进入了宇宙纪元。
L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球。
小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之间不会产生任何干扰。
为了鼓励科技创新, L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。
在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后,这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的物流公司的阶段性工作就完成了。
如果小 P 可以自由选择将哪一条航道改造成虫洞, 试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?
Input Format
第一行包括两个正整数 n,m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号。
接下来 n−1 行描述航道的建设情况,其中第 i 行包含三个整数 ai,bi 和 ti,表示第 i 条双向航道修建在 ai 与 bi 两个星球之间,任意飞船驶过它所花费的时间为 ti。数据保证 1≤ai,bi≤n 且 0≤ti≤1000。
接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 uj 和 vj,表示第 j 个运输计划是从 uj 号星球飞往 vj号星球。数据保证 1≤ui,vi≤n
Output Format
输出文件只包含一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。
n,m<=300000
Solution
先分析一下题目,n个点n-1条边且图联通,明显是树结构,
不难发现,题目是求最大值最小,不妨用二分答案
那么如何验证呢,对于每个计划,检查是否存在一些不合法线路,即两点间最短距离>mid,那么显然我们要选一条边作为虫洞,而且是所有不合法线路都经过的边
我们开一个数组sum[i]表示编号为i的边被多少条线路覆盖,那么对于所有不合法线路都经过的边,找一个最长的一条,把它设为虫洞,为最优
那么关键在于如何维护数组sum
经过shawn_xc学长的指导,用树上差分可以解决,
当发现一条不合法路径u to v时,令sum[u]++,sum[v]++,sum[lca(u,v)]-=2,即树上差分
最后就判断一下满足即可被所以不合法路线经过的边中最长的边设为虫洞后是否可行即可
Code
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define N 300010
using namespace std;
struct plan
{
int u, v, lca, dis;
} node[N];
struct info {
int to, nex, w;
} e[N * 2];
int n, m, head[N * 2], tot;
int l, r, edge[N];
bool vis[N];
int _log, fa[N][19], dep[N], dis[N];
inline int read() {
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-')f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}
inline void add_edge(int u, int v, int w) {
e[++tot].to = v;
e[tot].w = w;
e[tot].nex = head[u];
head[u] = tot;
}
void dfs(int u) {
vis[u] = 1;
for (int i = 1; i <= _log; ++i)
fa[u][i] = fa[fa[u][i - 1]][i - 1];
for (int i = head[u]; i; i = e[i].nex) {
int v = e[i].to;
if (vis[v]) continue;
edge[v] = i;
dep[v] = dep[u] + 1;
fa[v][0] = u;
dis[v] = dis[u] + e[i].w;
dfs(v);
}
}
int LCA(int u, int v) {
if (dep[u] > dep[v]) swap(u, v);
int d = dep[v] - dep[u];
for (int i = 0; i <= _log; ++i)
if (d & (1 << i))
v = fa[v][i];
if (u == v) return u;
for (int i = _log; i >= 0; i--)
if (fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
return fa[u][0];
}
int sum[N];
void update(int u, int fa) {
for (int i = head[u]; i; i = e[i].nex) {
int v = e[i].to;
if (v == fa) continue;
update(v, u);
sum[u] += sum[v];
}
}
bool pd(int mid) {
int tot = 0, dec = 0;
memset(sum, 0, sizeof(sum));
for (int i = 1; i <= m; ++i)
if (node[i].dis > mid) {
tot++;
dec = max(dec, node[i].dis - mid);
sum[node[i].u]++;
sum[node[i].v]++;
sum[node[i].lca] -= 2;
}
update(1, 1);
for (int i = 1; i <= n; ++i)
if (sum[i] == tot && e[edge[i]].w >= dec) return 1;
return 0;
}
int main() {
n = read(), m = read();
_log = log(n) / log(2);
for (int i = 1; i < n; ++i) {
int u = read(), v = read(), w = read();
add_edge(u, v, w);
add_edge(v, u, w);
}
dfs(1);
for (int i = 1; i <= m; ++i) {
int u = read(), v = read();
node[i].u = u, node[i].v = v;
node[i].lca = LCA(u, v);
node[i].dis = (dis[u] + dis[v]) - 2 * dis[node[i].lca];
r = max(r, node[i].dis);
}
int Ans;
while (l <= r) {
int mid = (l + r) >> 1;
if (pd(mid))
Ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%d\n", Ans);
return 0;
}
NOIP2015运输计划(树上前缀和+LCA+二分)的更多相关文章
- [NOIP2015]运输计划 线段树or差分二分
目录 [NOIP2015]运输计划 链接 思路1 暴力数据结构 思路2 二分树上差分 总的 代码1 代码2 [NOIP2015]运输计划 链接 luogu 好久没写博客了,水一篇波. 思路1 暴力数据 ...
- bzoj 4326: NOIP2015 运输计划【树链剖分+二分+树上差分】
常数巨大,lg上开o2才能A 首先预处理出运输计划的长度len和lca,然后二分一个长度w,对于长度大于w的运输计划,在树上差分(d[u]+1,d[v]+1,d[lca]-2),然后dfs,找出所有覆 ...
- NOIP2015 运输计划 (树上差分+二分答案)
---恢复内容开始--- 题目大意:给你一颗树,你可以把其中一条边的边权改成0,使给定的一些树链的权值和的最大值最小 把lenth定义为未修改边权时的答案 考虑二分答案,如果二分的答案成立,设修改成0 ...
- BZOJ 4326 NOIP2015 运输计划(树上差分+LCA+二分答案)
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Submit: 1388 Solved: 860 [Submit][Stat ...
- LOJ2425 NOIP2015 运输计划 【二分+LCA+树上差分】*
LOJ2425 NOIP2015 运输计划 LINK 题意:给你一颗树,可以将任意一条边的权值变成0,然后求m条路径的长度的最小值 思路: 先二分最后的距离ans,然后我们把路程大于ans的所有路径拿 ...
- NOIP2015 运输计划(二分+LCA+差分)
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 308 Solved: 208[Submit][Status] ...
- BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1930 Solved: 1231[Submit][Statu ...
- [NOIP2015]运输计划 D2 T3 LCA+二分答案+差分数组
[NOIP2015]运输计划 D2 T3 Description 公元2044年,人类进入了宇宙纪元. L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有 ...
- BZOJ 4326:NOIP2015 运输计划(二分+差分+lca)
NOIP2015 运输计划Description公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所 ...
随机推荐
- 静态include与动态include的区别
jsp中的include有两种形式,分别是:<%@ include file=""%><jsp:include page="" flush=& ...
- 201521123072《java程序设计》第十四周学习总结
201521123072<java程序设计>第十四周学习总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库 ...
- select应用于read函数 超时非阻塞方式
/* * "Timed" read - timout specifies the # of seconds to wait before * giving up (5th argu ...
- Struts2第二篇【开发步骤、执行流程、struts.xml讲解、defalut-struts讲解】
前言 我们现在学习的是Struts2,其实Struts1和Struts2在技术上是没有很大的关联的.Struts2其实基于Web Work框架的,只不过它的推广没有Struts1好,因此就拿着Stru ...
- java程序员该工作还是游戏?
前阵子我终于下定决心,删掉了硬盘里所有的游戏. 身为一个程序猿,每天都要和各种新技术打交道,闲暇时间,总还得看一下各大论坛,逛逛博客园啥的,给自己充充电.游戏的话,其实我自小就比较喜欢,可以算是一种兴 ...
- Kindle 推送教程:教你用电子邮箱推送电子书
Kindle 推送是什么意思?如何通过电子邮件附件推送?或许刚刚接触 Kindle 的朋友对这个概念不是很清楚,其实所谓 Kindle 推送是指亚马逊提供的一个"Kindle 个人文档服务& ...
- thinkphp的select和find的区别
hinkphp是比较好的php开发框架,能比较快速的开发MVC架构的管理系统,我们需要用到 select()和find()方法,两个方法都能返回数据集数组,但有什么不同呢?先看一下我的代码对比:$te ...
- ThinkPHP中,display和assign用法详解
thinkphp 模板显示display和assign的用法 $this->assign('name',$value); //在 Action 类里面使用 assign 方法对模板变量赋值,无论 ...
- Hbase 技术细节笔记(上)
欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:张秀云 前言 最近在跟进Hbase的相关工作,由于之前对Hbase并不怎么了解,因此系统地学习了下Hbase,为了加深对Hbase的 ...
- Springmvc学习笔记(一)
一.sprinvmvc的介绍 1.1.Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面.Spring 框架提供了构建 Web 应用程序的全 ...