[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 掌管一家物流公司, 该 ...
随机推荐
- H5视频、音频不能自动播放,Uncaught (in promise) DOMException: play() failed because the user didn't
错误原因:Chrome的autoplay政策在2018年4月做了更改. 解决办法: 第一步,在chrome浏览器中输入:chrome://flags/#autoplay-policy 第二步,在Aut ...
- js json字符串与json对象互相转换(最全)
1.json字符串转json对象 使用场景:通常在取json字符串里具体的值时,会用到. var jsonString = '{"name":"Marydon&quo ...
- Ubuntu18.4编译pmon,缺少makedepend和pmoncfg
提示makedepend找不到解决方法:$ apt-cache search makedependxutils-dev - X Window System utility programs for d ...
- Linux 网络通信 API详解【转载】
TCP/IP分层模型 OSI协议参考模型,它是基于国际标准化组织(ISO)的建议发展起来的, 它分为7个层次:应用层.表示层.会话层.传输层.网络层.数据链路层及物理层. 这个7层的协议模型虽然规定得 ...
- Uboot启动流程分析(一)
1.前言 Linux系统的启动需要一个bootloader程序,该bootloader程序会先初始化DDR等外设,然后将Linux内核从flash中拷贝到DDR中,最后启动Linux内核,uboot的 ...
- .NET Core 多框架支持(net45+netstandard20)实践中遇到的一些问题总结
.NET Core 多框架支持(net45+netstandard20)实践中遇到的一些问题总结 前言 本文主要是关于.NET Standard 代码 在多框架 和 多平台 支持自己实践过程中遇到的一 ...
- 解锁云原生 AI 技能|在 Kubernetes 上构建机器学习系统
本系列将利用阿里云容器服务,帮助您上手 Kubeflow Pipelines. 介绍 机器学习的工程复杂度,除了来自于常见的软件开发问题外,还和机器学习数据驱动的特点相关.而这就带来了其工作流程链路更 ...
- System.InvalidOperationException: 'Cannot create more than one System.Windows.Application instance in the same AppDomain.'
System.Windows.Application is a singleton: its constructor must only be invoked once (including App. ...
- C#关于函数重载的坑
今天在调用被重载的函数时,发现一个问题 private ProductRegisterResponse InitResponse(int code, string message, string pw ...
- Linux帮助——获取帮助
Linux帮助——获取帮助 摘要:本文主要学习了Linux众多命令中最基础的帮助命令. 介绍 作用 Linux的所有操作都可以通过命令行来完成,所以学习Linux最好从命令行开始.因为Linux的命令 ...