[luogu2680] 运输计划
题面
很明显, 由于是求最长路的最小值, 我们可以使用二分求解. 我们二分一个长度\(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] 运输计划的更多相关文章
- [luogu2680] 运输计划 (lca+二分+树上差分)
传送门 Description Input Output 一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间. Sample Input 6 3 1 2 3 1 6 4 3 1 7 4 3 ...
- bzoj 4326: NOIP2015 运输计划
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个 ...
- noip2015 运输计划
描述 公元 2044 年,人类进入了宇宙纪元.L 国有 nn 个星球,还有 n−1n−1 条双向航道,每条航道建立在两个星球之间,这 n−1n−1 条 航道连通了 L 国的所有星球. 小 P 掌管一家 ...
- 【bzoj4326】[NOIP2015]运输计划
题目描述 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家物流公司, 该 ...
- [题解]vijos 运输计划
Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家 ...
- NOIP2015 运输计划(bzoj4326)
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 886 Solved: 574[Submit][Status] ...
- UOJ #150 【NOIP2015】 运输计划
题目描述 公元 \(2044\) 年,人类进入了宇宙纪元. \(L\) 国有 \(n\) 个星球,还有 \(n-1\) 条双向航道,每条航道建立在两个星球之间,这 \(n-1\) 条航道连通了 \(L ...
- [bzoj4326][NOIP2015]运输计划
Description 公元2044年,人类进入了宇宙纪元. 国有个星球,还有条双向航道,每条航道建立在两个星球之间,这条航道连通了国的所有星球. 小掌管一家物流公司,该公司有很多个运输计划,每个运输 ...
- 【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 703 Solved: 461[Submit][Status] ...
随机推荐
- Java代理(一)
先来看看Java的静态代理,假设有如下接口和实现方法: package proxy; public interface Subject { public void request(); public ...
- 解决:maven 项目添加 pom 的 oracle 依赖
前言:maven 项目需要在 pom 文件中添加 oracle 的依赖. 如果报错:报找不到驱动:java.lang.ClassNotFoundException: oracle.jdbc.drive ...
- .NET4.5新特性async和await修饰符实现异步编程
开篇 每一个版本的.net都会引入一些新的特性,这些特性方便开发人员能够快速实现一些功能.虽然.net版本一直在更新,但是新版本对旧版本的程序都是兼容的,在这一点上微软做的还是非常好的.每次学一个新内 ...
- java多线程3种方式
Java多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式线程执行完后都没 ...
- Flare-On4 解题复现
01 是一个 html 页面, 用开发者工具看看,发现是简单的 js 加密. 猜测加密算法可逆,试着用 PyvragFvqrYbtvafNerRnfl@syner-ba.pbz 作为输入,然后调试 , ...
- 0ctf2017-babyheap
前言 又是一道令人怀疑人生的 baby 题. 这道题利用思路非常巧妙,通过 堆溢出 和 fastbin 的机制构造了 information leak, 然后通过 fastbin attack 可以读 ...
- 润乾V4的最小化部署方式
在接触到的很多项目实际应用中,部署润乾V4都是使用润乾V4设计器自带的WEB发布向导,直接生成webRoot目录,然后将该目录下的所有文件COPY到项目目录下,然后修改web.xml文件和rep ...
- linux 文件操作命令 touch、cat、more、less、head、tail
touch /bin/touch 创建空文件 linux 创建文件可以使用特殊符号,/除外 touch test test1 创建了两个文件touch "test test1" 创 ...
- JS DOM节点增删改查 属性设置
一.节点操作 增 createElement(name)创建元素 appendChild();将元素添加 删 获得要删除的元素 获得它的父元素 使用removeChild()方法删除 改 第一种方 ...
- MYSQL 5.7 sqlmode 行为
最近碰到了sql_mode 的一些问题,故进行了研究,根据实际情况研究其行为. sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ER ...