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+二分)的更多相关文章

  1. [NOIP2015]运输计划 线段树or差分二分

    目录 [NOIP2015]运输计划 链接 思路1 暴力数据结构 思路2 二分树上差分 总的 代码1 代码2 [NOIP2015]运输计划 链接 luogu 好久没写博客了,水一篇波. 思路1 暴力数据 ...

  2. bzoj 4326: NOIP2015 运输计划【树链剖分+二分+树上差分】

    常数巨大,lg上开o2才能A 首先预处理出运输计划的长度len和lca,然后二分一个长度w,对于长度大于w的运输计划,在树上差分(d[u]+1,d[v]+1,d[lca]-2),然后dfs,找出所有覆 ...

  3. NOIP2015 运输计划 (树上差分+二分答案)

    ---恢复内容开始--- 题目大意:给你一颗树,你可以把其中一条边的边权改成0,使给定的一些树链的权值和的最大值最小 把lenth定义为未修改边权时的答案 考虑二分答案,如果二分的答案成立,设修改成0 ...

  4. BZOJ 4326 NOIP2015 运输计划(树上差分+LCA+二分答案)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MB Submit: 1388  Solved: 860 [Submit][Stat ...

  5. LOJ2425 NOIP2015 运输计划 【二分+LCA+树上差分】*

    LOJ2425 NOIP2015 运输计划 LINK 题意:给你一颗树,可以将任意一条边的权值变成0,然后求m条路径的长度的最小值 思路: 先二分最后的距离ans,然后我们把路程大于ans的所有路径拿 ...

  6. NOIP2015 运输计划(二分+LCA+差分)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 308  Solved: 208[Submit][Status] ...

  7. BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1930  Solved: 1231[Submit][Statu ...

  8. [NOIP2015]运输计划 D2 T3 LCA+二分答案+差分数组

    [NOIP2015]运输计划 D2 T3 Description 公元2044年,人类进入了宇宙纪元. L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有 ...

  9. BZOJ 4326:NOIP2015 运输计划(二分+差分+lca)

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

随机推荐

  1. 201521123093 java 第十三周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu ...

  2. 201521123095 《Java程序设计》第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 Q1.finally 题目4-2 1.1 截图你的提交结果( ...

  3. ASP.Net开发WebAPI跨域访问(CORS)的精简流程

    1: Web.config里有一行: <remove name="OPTIONSVerbHandler" /> 这个要删除. 2: nuget安装Microsoft.A ...

  4. display:flex css

    本文介绍下flex的用法和属性 这个一个自适应的3列盒子 <div class="flex"> <div style="background-color ...

  5. CentOS7安装后配置MariaDB

    安装后,优先推荐先对安全设置进行配置,键入命令 sudo mysql_secure_installation 键入当前密码,当前没有,直接回车,之后跟随提示会问几个问题:设置 root 密码? / 移 ...

  6. noip的一些模板(参考了神牛的博客)

    一.图论 1.单源最短路 洛谷P3371 (1)spfa 已加SLF优化 419ms #include <iostream> #include <cstdio> #includ ...

  7. Racing Car Computer dp

    Racing Car Computer Input: Standard Input Output: Standard Output   The racing cars of today are equ ...

  8. Ubuntu16笔记本双显卡安装NVIDIA驱动

    blockquote { direction: ltr; color: rgb(0, 0, 0) } blockquote.western { font-family: "Liberatio ...

  9. Windows下如何创建低权限进程

       1.  前言 在使用 Sysinternals 出品的 Process Explorer 过程中,对 “Run as Limited User” 功能的实现方式颇感兴趣,一番搜寻之下发现Mark ...

  10. 数据的分类-JavaScript数据类型

    JavaScript数据类型 1.数据类型是什么? 我们接触的绝大多数程序语言来说,把数据都进行了分类,包括数字.字符.逻辑真假:int,long,string,boolean....等等:我们都知道 ...