题面

​ 很明显, 由于是求最长路的最小值, 我们可以使用二分求解. 我们二分一个长度\(mid\), 将所有使得\(dis(u, v)\)大于\(mid\)的点对\((u, v)\)找出, 设总共有\(m\)条这样的边, 那么我们需要改变的改变边一定是被这\(m\)条边都经过的边, 所以我们只需要找到满足这个要求的长度最大的改变边使得这\(m\)条边中最长的一条减去这一条改变边小于等于\(mid\) 就可以了, 如果没有这样的边就说明\(mid\)小了. 那要怎么找这条改变边呢??? 树上差分就可以了啊, 将边权下放为点权, 让\(cnt[u]++\), \(cnt[v]++\), \(cnt[lca(u, v)] -= 2\)就可以了, 至于某个点被经过的次数就将他子树的累加起来即可.

具体代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define N 300005
using namespace std; int n, m, head[N], tot, fa[N], cost[N], road[N], cnt, num[N], vis[N], l, r, mid, ans;
struct node
{
int to, cost, next;
} edge[N << 1];
struct Ask
{
int u, v, lca, dis;
} ask[N];
struct node2
{
int v, id;
};
vector<node2> LCA[N]; inline int read()
{
int x = 0, w = 1;
char c = getchar();
while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * w;
} inline void add(int u, int v, int w) { edge[++tot].to = v; edge[tot].cost = w; edge[tot].next = head[u]; head[u] = tot; } int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); } void tarjan(int u, int ff)
{
vis[u] = 1;
for(int i = head[u]; i; i = edge[i].next)
{
int v = edge[i].to; if(v == ff) continue;
cost[v] = edge[i].cost; road[v] = road[u] + edge[i].cost;
tarjan(v, u); fa[v] = u;
}
for(int i = 0; i < (int) LCA[u].size(); i++)
if(vis[LCA[u][i].v] && !ask[LCA[u][i].id].lca)
ask[LCA[u][i].id].lca = find(LCA[u][i].v);
} void dfs(int u, int fa)
{
for(int i = head[u]; i; i = edge[i].next)
{
int v = edge[i].to; if(v == fa) continue;
dfs(v, u); num[u] += num[v];
}
} bool check(int mid)
{
memset(num, 0, sizeof(num));
int mx = -1, sum = 0;
for(int i = 1; i <= m; i++)
if(ask[i].dis > mid) { sum++; mx = max(mx, ask[i].dis); num[ask[i].u]++; num[ask[i].v]++; num[ask[i].lca] -= 2; }
dfs(1, 0);
for(int i = 1; i <= n; i++)
if(num[i] >= sum && mx - cost[i] <= mid) return 1;
return 0;
} int main()
{
n = read(); m = read();
for(int i = 1; i <= n; i++) fa[i] = i;
for(int i = 1; i < n; i++)
{
int u = read(), v = read(), w = read();
add(u, v, w); add(v, u, w);
}
for(int i = 1; i <= m; i++)
{
ask[i].u = read(); ask[i].v = read();
LCA[ask[i].u].push_back((node2){ ask[i].v, i });
LCA[ask[i].v].push_back((node2){ ask[i].u, i });
}
tarjan(1, 0);
for(int i = 1; i <= m; i++)
{
r = max(r, road[ask[i].u] + road[ask[i].v] - road[ask[i].lca] * 2);
ask[i].dis = road[ask[i].u] + road[ask[i].v] - road[ask[i].lca] * 2;
}
ans = r;
while(l <= r)
{
mid = (l + r) >> 1;
if(check(mid)) { ans = mid; r = mid - 1; }
else l = mid + 1;
}
printf("%d\n", ans);
return 0;
}

[luogu2680] 运输计划的更多相关文章

  1. [luogu2680] 运输计划 (lca+二分+树上差分)

    传送门 Description Input Output 一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间. Sample Input 6 3 1 2 3 1 6 4 3 1 7 4 3 ...

  2. bzoj 4326: NOIP2015 运输计划

    4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个 ...

  3. noip2015 运输计划

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

  4. 【bzoj4326】[NOIP2015]运输计划

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

  5. [题解]vijos 运输计划

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

  6. NOIP2015 运输计划(bzoj4326)

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

  7. UOJ #150 【NOIP2015】 运输计划

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

  8. [bzoj4326][NOIP2015]运输计划

    Description 公元2044年,人类进入了宇宙纪元. 国有个星球,还有条双向航道,每条航道建立在两个星球之间,这条航道连通了国的所有星球. 小掌管一家物流公司,该公司有很多个运输计划,每个运输 ...

  9. 【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分

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

随机推荐

  1. java设计模式-----10、享元模式

    Flyweight模式也叫享元模式,是构造型模式之一,它通过与其他类似对象共享数据来减小内存占用.它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件:它适合用于只是因重复而导致使 ...

  2. python__new__与__init__的区别

    __new__ __init__区别 1 class A(object): 2 def __init__(self,*args, **kwargs): 3 print "init A&quo ...

  3. Git 学习之Git 基础(二)

    Git 基础 读完本章你就能上手使用 Git 了.本章将介绍几个最基本的,也是最常用的 Git 命令,以后绝大多数时间里用到的也就是这几个命令.读完本章,你就能初始化一个新的代码仓库,做一些适当配置: ...

  4. C# 如何在Linux操作系统下读取文件

    发布在Window环境上的微服务需要部署在Linux环境上,本以为没有什么问题,结果因为一处读取文件路径的原因报错了,在此记录一下两个问题:1.C#如何判断当前运行环境是什么操作系统:2.C#读取文件 ...

  5. thinkPHP3.2.2 数据库对表的操作

    增加:M('表名')->add($data); 删除:M('表名')->delete($id); 更新:M('表名')->save($data); 查询:M('表名')->se ...

  6. 【linux】扒站命令之利用wget快速扒站利用wget快速扒站

    在Linux下,通过一个命令就可以把整个站相关的文件全部下载下来. wget -r -p -k -np 参数说明: -r : 递归下载 -p : 下载所有用于显示 HTML 页面的图片之类的元素 -k ...

  7. Spring Boot—12URL映射

    package com.sample.smartmap.controller; import java.util.List; import org.springframework.beans.fact ...

  8. 使用 NGINX 进行微程序缓存的好处

    [编者按]本文作者为 Owen Garrett,主要介绍使用 nginx 进行微程序缓存的好处,辅之以生动的实例.文章系国内 ITOM 管理平台 OneAPM 编译呈现. NGINX 和 NGINX ...

  9. shell_script2

    一.函数 1.简介 Shell函数类似于Shell脚本,里面存放了一系列的指令 不过,Shell的函数存在于内存,而不是硬盘文件,所以速度很快 另外,Shell还能对函数进行预处理,所以函数的启动比脚 ...

  10. .NET基础一

    .NET FrameWork是用于Windows的新托管代码编程模型,它包含CLR(Common Language Runtime)以及BCL(Base CLass Library)构成. 一.CLR ...