[CODEVS4632][BZOJ4326]运输计划
|
题目描述 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 Description |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 第一行包括两个正整数 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 Description |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
输出文件只包含一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
样例输入 Sample Input |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
6 3 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
样例输出 Sample Output |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
11 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
数据范围及提示 Data Size & Hint |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
之前的一些废话:还有一天出国,某年NOIP,由于我对NOIP的题都有心理阴影,所以一直不敢把这些没做的最后一题的坑填上,然而今天还是面对了这道题,并且能很快想出做法还是很开心的。
题解:首先蜜汁想到了二分(我也不知道为什么),二分的套路,判断当前解mid是否可行,如何判断是否可行呢?其实就是查看当前这些航线能否通过删去某一条对应的边使得每条路径和都小于mid即可。对于那些原来路径和就比mid小的航线就可以无视它们,只考虑那些需要进行裁剪的航线,我们现在需要找到一条边,使得所有比mid大的航线都必须经过这条边(要不然那些不过这条边的航线就无法进行剪裁,更不必说当前解可行了)。满足这种条件的边可能有很多,我们根据贪心的思路就选取最大的边,然后用路径和最大的那条航线减去这条边权(如果最大的那条航线都可以的话比他小的肯定都可以),并且判断这个结果与mid的大小关系,如果小于等于mid,那就说明当前解可行。
当然这只是一些想法,具体做法如下:首先我们通过dfs预处理出1到所有点的距离,这样方便后续航线路径和的计算,并把每一条航线进行结构体捆绑,按照路径和进行从小到大的排序。之后开始二分,上界是最大航线的路径和,下界是0,判断当前解是否可行的话用upper_bound在有序的航线中查出比mid大的第一条航线,然后开始考虑这些路径,需要找到一条边过所有航线,这个可以拿树上差分在O(n)时间内完成,最后扫一遍所有的边,判断tag[i]是否等于总航线的数值,并取其中的最大值,然后用路径和最大的那条航线减去这条边权,并且判断这个结果与mid的大小关系,如果小于等于mid,那就说明当前解可行。在树上差分的时候需要求出lca,因为我不会写O(1)求lca的,所以会多一个log,但是我们在预处理所有航线的路径和的过程中就会算出lca的值,所以提前存好即可。复杂度O((n+logm)logn)
二分照样很坑爹,改过N次二分的写法还是觉得不够稳,最后决定放弃,用最原始的写法,毕竟这样保险:

代码:
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
#define mem(a,b) memset(a,b,sizeof(a))
inline int read()
{
int x=,f=;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-;c=getchar();}
while(isdigit(c)){x=x*+c-'';c=getchar();}
return x*f;
}
const int maxn=,maxm=;
int n,m,a,b,c,ce=-,es,top[maxn],first[maxn],deep[maxn],fa[maxn],size[maxn],dis[maxn],ms[maxn],L,R,mid;
int tag[maxn],maxw,w[maxn];
struct Edge
{
int u,v,w,next;
Edge() {}
Edge(int _1,int _2,int _3,int _4) :u(_1),v(_2),w(_3),next(_4) {}
}e[maxn<<];
struct path
{
int u,v,lc,len;
path() {}
path(int _1,int _2,int _3,int _4):u(_1),v(_2),lc(_3),len(_4) {}
bool operator < (const path& s)const {return len<s.len;}
}line[maxm];
void addEdge(int a,int b,int c)
{
e[++ce]=Edge(a,b,c,first[a]);first[a]=ce;
e[++ce]=Edge(b,a,c,first[b]);first[b]=ce;
}
void dfs(int now,int pa)
{
size[now]=;
for(int i=first[now];i!=-;i=e[i].next)
if(e[i].v!=pa)
{
deep[e[i].v]=deep[now]+;
dis[e[i].v]=dis[now]+e[i].w;
w[e[i].v]=e[i].w;
dfs(e[i].v,now);
if(size[ms[now]]<size[e[i].v])ms[now]=e[i].v;
size[now]+=size[e[i].v];
fa[e[i].v]=now;
}
}
void divide(int now,int chain)
{
top[now]=chain;
if(ms[now])divide(ms[now],chain);
for(int i=first[now];i!=-;i=e[i].next)if(e[i].v!=fa[now] && e[i].v!=ms[now])divide(e[i].v,e[i].v);
}
int lca(int a,int b)
{
while(top[a]!=top[b])
{
if(deep[top[a]]<deep[top[b]])swap(a,b);
a=fa[top[a]];
}
return deep[a]<deep[b] ? a : b;
}
void pushup(int now)
{
for(int i=first[now];i!=-;i=e[i].next)
if(fa[now]!=e[i].v)pushup(e[i].v),tag[now]+=tag[e[i].v];
}
bool check(int mid)
{
int maxw=;
path tmp=path(,,,mid);
int pos=upper_bound(line,line+m,tmp)-line;
mem(tag,);
for(int i=pos;i<m;i++)
{
tag[line[i].u]++;tag[line[i].v]++;
tag[line[i].lc]-=;
}
pushup();
for(int i=;i<=n;i++)if(tag[i]==m-pos)maxw=max(maxw,w[i]);
return line[m-].len-maxw<=mid;
}
int main()
{
mem(first,-);
n=read();m=read();
for(int i=;i<n;i++)a=read(),b=read(),c=read(),addEdge(a,b,c);
dfs(,);divide(,);
for(int i=;i<m;i++)
{
a=read();b=read();c=lca(a,b);
line[i]=path(a,b,c,dis[a]+dis[b]-*dis[c]);
}
sort(line,line+m);
L=;R=line[m-].len;
while(R-L>)
{
mid=(L+R)>>;
if(check(mid))R=mid;
else L=mid;
}
if(check(L))printf("%d\n",L);
else printf("%d\n",R);
return ;
}
总结:树上差分真的太好使了!!二分还是老老实实按上面那么写吧。
[CODEVS4632][BZOJ4326]运输计划的更多相关文章
- bzoj4326 运输计划
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n ...
- NOIP2015 D2T3 洛谷2680 BZOJ4326 运输计划 解题报告
前言:个人认为这是历年NOIP中比较简单的最后一题了,因此将自己的思路与大家分享. 题目大意: 给一棵无根树,给出m条路径.允许将树上的一条边的权值改为0.求m条路径长度最大值的最小值.n,m< ...
- [BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划
[BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划 试题描述 公元 2044 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n− ...
- 【bzoj4326】[NOIP2015]运输计划
题目描述 公元 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] ...
- [bzoj4326][NOIP2015]运输计划
Description 公元2044年,人类进入了宇宙纪元. 国有个星球,还有条双向航道,每条航道建立在两个星球之间,这条航道连通了国的所有星球. 小掌管一家物流公司,该公司有很多个运输计划,每个运输 ...
- 【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 703 Solved: 461[Submit][Status] ...
- BZOJ4326或洛谷2680 运输计划
BZOJ原题链接 洛谷原题链接 用\(LCA\)初始化出所有运输计划的原始时间,因为答案有单调性,所以二分答案,然后考虑检验答案. 很容易想到将所有超出当前二分的答案的运输计划所经过的路径标记,在这些 ...
- 【bzoj4326】[NOIP2015]运输计划 二分答案+LCA
题目描述 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家物流公司, 该 ...
随机推荐
- hibernate中flush()、refresh()、clear()缓存操作
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ flush():使数据库中的对象和session缓存中的对象的状态 ...
- 【SpringCloud之pigx框架学习之路 】1.基础环境安装
[SpringCloud之pigx框架学习之路 ]1.基础环境安装 [SpringCloud之pigx框架学习之路 ]2.部署环境 1.Cmder.exe安装 (1) windows常用命令行工具 下 ...
- word设置标题1,标题2,标题3项目编号联动
word经常要按层级显示标题,并且标题样式之间要联动 如: 设置办法: word内鼠标右键 2.选择项目符号和编号 3.选择一个样式并自定义 将级别链接到样式.选择对应标题样式即可实现联动.
- vuex 源码解析(四) mutation 详解
mutation是更改Vuex的store中的状态的唯一方法,mutation类似于事件注册,每个mutation都可以带两个参数,如下: state ;当前命名空间对应的state payload ...
- mysql批量更新数据(性能优化) 第一种方式
首先想到的是,一条一条更新的速度太慢了,然后就想批量更新,一次更新N条数据.实践是检验真理的唯一标准,不一会儿,代码就敲完了,重新试了一下,效果依旧不理想.啊哦,真是要崩溃!后面又想到了利用异步,我一 ...
- Spring源码系列 — Bean生命周期
前言 上篇文章中介绍了Spring容器的扩展点,这个是在Bean的创建过程之前执行的逻辑.承接扩展点之后,就是Spring容器的另一个核心:Bean的生命周期过程.这个生命周期过程大致经历了一下的几个 ...
- Ubuntu 限制 指定端口和IP 访问
限制端口和IP的时候 要注意别自己登陆不进去了,要不就惨了. 只允许指定的IP访问服务器的指定端口:22 只允许访问的ip: 192.168.1.1 192.168.1.2 192.168.1.3,禁 ...
- 第三方web ide开发环境下vuejs开发HMR环境搭建-码农这样开发是快乐的!
vuejs是一个非常优秀的前端框架,利用该框架可以快速开发出任何web app,之所以vuejs开发非常高效快捷,其中最重要的一点就是利用webpakc提供的HMR(热模块替换)特性,可以边写vue组 ...
- nodejs-翻转算法
nodejs-翻转算法 /** * Created by moon on 2019/12/14. */ //程序运行完成时一定要有输出语句,本工具才能正确展示运行结果. function abc() ...
- 工作笔记--Python自动切换host
修改host代码: #coding:utf-8import os,time pwd = os.path.dirname(__file__) #获取当前文件夹的绝对路径pull_host_cmd = ' ...