[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] ...
随机推荐
- nginx 错误日志分析
502 1.查看nginx错误日志 tailf /data/log/nginx/error.log // :: [error] #: * recv() failed (: Connection res ...
- MySQL数据库的回滚失败(JAVA)
这几天在学习MySQL数据的知识,有一个小测试,用来测试数据库的提交和回滚. 刚开始的时候真的没把这个当回事,按照正常的步骤来讲的话,如下所示,加载驱动,获取数据库的连接,并且把数据库的自动提交给关闭 ...
- 移动端h5实现拍照上传图片并预览&webuploader
.移动端实现图片上传并预览,用到h5的input的file属性及filereader对象:经测除了android上不支持多图片上传,其他基本ok实用: 一:先说一下单张图片上传(先上代码): html ...
- call aplly笔记
<script> /*1.每个函数都包含两个非继承而来的方法:apply()和call(). 2.他们的用途相同,都是在特定的作用域中调用函数. 3.接收参数方面不同,apply()接收两 ...
- JQuery和原生JavaScript实现网页定位导航特效
慕课网的一个小课程,练习了一遍,不足之处,欢迎指正(照片在本地,大家可以着重看代码哈): <!DOCTYPE html> <html lang="en"> ...
- mvc里全局错误日志
第一步在项目中找到App_Start文件夹下建立一个错误日志过滤器. 第二步在Global.asax文件中注册下日志过滤器 第三步: 继承一个ExceptionFilterAtrribute 第四步: ...
- overload与override的区别
override(重写,覆盖) 1.方法名.参数.返回值相同. 2.子类方法不能缩小父类方法的访问权限. 3.子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常). 4.存在于父类和子类之 ...
- android studio使用openssl
前言 逆向的基础是开发, 逆向分析时很多时候会使用一些公开的加密函数来对数据进行加密,通过使用 openssl 熟悉下. 正文 首先得先编译出来 openssl,然后把它们复制到你的工程目录下. in ...
- iphone使用linux命令apt-get也没有问题
那么教程开始: 首先安装cydia这个越了yu就有自带的哦 然后添加源,比如apt.91.我忘了,大家可以在http://frank-dev-blog.club/?post=45找一个 查找termi ...
- 微信小程序接入腾讯云IM即时通讯(会话列表)
会话列表功能概述: 登录 :先用自己的账号登录腾讯云: 获取会话列表 :登录之后再获取会话列表: 更新未读消息数量 :获取会话列表之后更新未读消息数量 WXML代码(自己写的将就看一下) <vi ...