[NOIP 2015TG D2T3] 运输计划
题目背景
公元 2044 年,人类进入了宇宙纪元。
题目描述
L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球。
小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物
流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道 是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之 间不会产生任何干扰。
为了鼓励科技创新,L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小 P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。
在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后, 这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的 物流公司的阶段性工作就完成了。
如果小 P 可以自由选择将哪一条航道改造成虫洞,试求出小 P 的物流公司完成阶段 性工作所需要的最短时间是多少?
输入输出格式
输入格式:
输入文件名为 transport.in。
第一行包括两个正整数 n、m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号。
接下来 n-1 行描述航道的建设情况,其中第 i 行包含三个整数 ai, bi 和 ti,表示第
i 条双向航道修建在 ai 与 bi 两个星球之间,任意飞船驶过它所花费的时间为 ti。
接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 uj 和 vj,表示第 j个 运输计划是从 uj 号星球飞往 vj 号星球。
输出格式:
输出 共1行,包含1个整数,表示小P的物流公司完成阶段性工作所需要的最短时间。
输入输出样例
6 3 1 2 3 1 6 4 3 1 7 4 3 6 3 5 5 3 6 2 5 4 5
11
说明
所有测试数据的范围和特点如下表所示
请注意常数因子带来的程序效率上的影响。
好烦呐。。。
让我们一步一步对这道难题深入分析。
1.整棵树在整个过程中改变的只有1条边的权值,其他边与树的结构都没变化,这是很重要的;
2.我们要在很短的时间内要知道这棵树中任意两点间的距离——那么我们就要选择比较优秀的算法了。由于n,m很大,所以我们能选的较为不错的,一个是用LCA来解,另一个就是用树链剖分(我个人认为树链剖分写起来更快,而且更容易查错);
3.我们必定要将m条路径中,起点终点的LCA求出,作为中转站,便于解题;
4.仔细读题目,任务是让我们求最小的最大值,那么我们自然而然会想到二分;
5.假设我们用树链剖分先将m条路线两点距离等需要的量预处理出来,需要mlogn的时间,而二分又是log级别的,所以主要考虑的还要放在二分的check上面;
6.check怎么来?不慌,按照题目中要求的。当然,不能枚举每条边再判断,否则这样的复杂度已经到了nlog(R-L),意味着判断的过程要在log级别以下,这是完全不可能的(你还要枚举路径呢(m条))。那怎么办?对于这题,check成功的条件更容易判断。怎样算check成功?假设,当前二分的最大值为high,如果m条路径中dis大于high的都记录下来(可以之前就排趟序),假设有cnt条,然后,我们要找一条边,将这条边权值变为0后,要达到m条路径的dis都小于等于high的目的,说明这cnt条“超标”路径必定经过这条边,并且dis[当前路径]-w[当前边]<=high,这样才行;
7.那怎么记录每条边被经过的次数?首先,我们会有一个暴力的想法(真的暴力),如果一条路径(x,y)“超标”,那么将x-->LCA(x,y)和y-->LCA(x,y)经过的边都加上1个经过次数。但是这样实在太慢(只有80分,算不错了),毕竟如果出现链状,时间就退化成线性的了(而且这个链也非可以剖分的树链)。那么怎么优化?我们想到了差分的方法(我真心没想到)。像上面这个例子,就把f[x]++,f[y]++,f[LCA(x,y)]-=2,其中f[i]表示的是从节点i到其父节点的次数(1当然没有),我们可以用DFS累加的方式求出所有边经过的次数。这样,check这个过程的复杂度就降到了O(n)左右,不虚了;
8.当然这种题目肯定都要卡常的,在评测时我加了一句话,出现了神奇的一幕。。。我先用第一种方法(步骤7里),在check开头加了一句if (a[1].dis>high+1000) return 0;(其中a数组按关键字dis从大到小排序),结果就A了!在第二种方法写上同样的东西,跑得反而没有第一种快,还TLE了1个点。。。[yun]蒽哼哼,我想,这也许就是“神剪枝”的威力吧。。。orz ○| ̄|_
下面给出两份代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define Me(Arr) memset(Arr,0,sizeof Arr); using namespace std; ,maxe=; int n,m,L,R,mid,ans; int lnk[maxn],nxt[maxe],son[maxe],w[maxe],id[maxe],wsin[maxn],pointto[maxn],tot; int size[maxn],fa[maxn],dep[maxn],gonxt[maxn],top[maxn]; int bel[maxn],wei[maxn],wtofa[maxn],cnt; int f[maxn]; struct data{ int x,y,dis,LCA; bool operator < (const data &u) const {return dis>u.dis;} }a[maxn]; int read(){ ; char ch=getchar(); ') ch=getchar(); +ch-',ch=getchar(); return x; } void INIT(){ tot=cnt=; Me(lnk); Me(nxt); Me(son); Me(w); Me(id); Me(wsin); Me(wtofa); Me(pointto); Me(size); Me(fa); Me(dep); Me(gonxt); Me(top); Me(wei); Me(bel); top[]=cnt=bel[]=,L=,R=-; } void add(int i,int x,int y,int z){ nxt[++tot]=lnk[x],son[tot]=y,w[tot]=z,id[tot]=i,lnk[x]=tot; } void DFS_1(int x,int u,int layer){ size[x]=,fa[x]=u,dep[x]=layer; for (int j=lnk[x]; j; j=nxt[j]) if (son[j]!=u){ DFS_1(son[j],x,layer+); size[x]+=size[son[j]],wtofa[son[j]]=w[j],pointto[son[j]]=id[j]; if (size[gonxt[x]]<size[son[j]]) gonxt[x]=son[j],wei[x]=w[j]; } } void DFS_2(int x){ if (gonxt[x]) top[gonxt[x]]=top[x],bel[gonxt[x]]=bel[x],DFS_2(gonxt[x]),wei[x]+=wei[gonxt[x]]; for (int j=lnk[x]; j; j=nxt[j]) if (son[j]!=fa[x]&&son[j]!=gonxt[x]) top[son[j]]=son[j],bel[son[j]]=++cnt,DFS_2(son[j]); } void prepare(){ DFS_1(,,); DFS_2(); } ?x:-x;} int get(int i,int x,int y){ ; while (bel[x]!=bel[y]) if (dep[top[x]]>dep[top[y]]) ret+=wei[top[x]]-wei[x]+wtofa[top[x]],x=fa[top[x]]; else ret+=wei[top[y]]-wei[y]+wtofa[top[y]],y=fa[top[y]]; ret+=abso(wei[x]-wei[y]); a[i].LCA=dep[x]<dep[y]?x:y; return ret; } void work(int u,int v,int LCA){ while (u!=LCA) f[pointto[u]]++,u=fa[u]; while (v!=LCA) f[pointto[v]]++,v=fa[v]; } bool jug(int high){ ].dis>high+) ; Me(f); ].dis-high,cnt=; ; i<=m; i++) if (a[i].dis>high) work(a[i].x,a[i].y,a[i].LCA),cnt++; else break; ; ; i<n; i++) ; ; } int main(){ n=read(),m=read(),INIT(); ; i<n; i++){ int x=read(),y=read(),z=read(); add(i,x,y,z),add(i,y,x,z); wsin[i]=z; } prepare(); ; i<=m; i++) a[i].x=read(),a[i].y=read(),a[i].dis=get(i,a[i].x,a[i].y),R=max(R,a[i].dis); sort(a+,a++m); while (L<=R){ mid=(L+R)>>; ; ; } printf("%d",ans); ; }
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define Me(Arr) memset(Arr,0,sizeof Arr); using namespace std; ,maxe=; int n,m,L,R,mid,ans; int lnk[maxn],nxt[maxe],son[maxe],w[maxe],tot; int size[maxn],fa[maxn],dep[maxn],gonxt[maxn],top[maxn]; int bel[maxn],wei[maxn],wtofa[maxn],cnt; int f[maxn]; struct data{ int x,y,dis,LCA; bool operator < (const data &u) const {return dis>u.dis;} }a[maxn]; int read(){ ; char ch=getchar(); ') ch=getchar(); +ch-',ch=getchar(); return x; } void INIT(){ tot=cnt=; Me(lnk); Me(nxt); Me(son); Me(w); Me(wtofa); Me(size); Me(fa); Me(dep); Me(gonxt); Me(top); Me(wei); Me(bel); top[]=cnt=bel[]=,L=,R=-; } void add(int i,int x,int y,int z){ nxt[++tot]=lnk[x],son[tot]=y,w[tot]=z,lnk[x]=tot; } void DFS_1(int x,int u,int layer){ size[x]=,fa[x]=u,dep[x]=layer; for (int j=lnk[x]; j; j=nxt[j]) if (son[j]!=u){ DFS_1(son[j],x,layer+); size[x]+=size[son[j]],wtofa[son[j]]=w[j]; if (size[gonxt[x]]<size[son[j]]) gonxt[x]=son[j],wei[x]=w[j]; } } void DFS_2(int x){ if (gonxt[x]) top[gonxt[x]]=top[x],bel[gonxt[x]]=bel[x],DFS_2(gonxt[x]),wei[x]+=wei[gonxt[x]]; for (int j=lnk[x]; j; j=nxt[j]) if (son[j]!=fa[x]&&son[j]!=gonxt[x]) top[son[j]]=son[j],bel[son[j]]=++cnt,DFS_2(son[j]); } void DFS_3(int x){ for (int j=lnk[x]; j; j=nxt[j]) if (son[j]!=fa[x]) DFS_3(son[j]),f[x]+=f[son[j]]; } void prepare(){ DFS_1(,,); DFS_2(); } ?x:-x;} int get(int i,int x,int y){ ; while (bel[x]!=bel[y]){ if (dep[top[x]]>dep[top[y]]) ret+=wei[top[x]]-wei[x]+wtofa[top[x]],x=fa[top[x]]; else ret+=wei[top[y]]-wei[y]+wtofa[top[y]],y=fa[top[y]]; } a[i].LCA=dep[x]<dep[y]?x:y; ret+=abso(wei[x]-wei[y]); return ret; } bool jug(int high){ ].dis>high+) ; ].dis<=high) ; Me(f); ].dis-high,cnt=; ; i<=m; i++) ,cnt++; else break; DFS_3(); ; i<=n; i++) ; ; } int main(){ n=read(),m=read(),INIT(); ; i<n; i++){ int x=read(),y=read(),z=read(); add(i,x,y,z),add(i,y,x,z); } prepare(); ; i<=m; i++) a[i].x=read(),a[i].y=read(),a[i].dis=get(i,a[i].x,a[i].y),R=max(R,a[i].dis); sort(a+,a++m); while (L<=R){ mid=(L+R)>>; ; ; } printf("%d",ans); ; }
[NOIP 2015TG D2T3] 运输计划的更多相关文章
- [NOIP2015 TG D2T3]运输计划
题目大意: 给你一棵n个节点的树,有边权,有多个任务,每个要求从ui号节点到 vi号节点去.m 个计划, 这 m 个计划会同时开始.当这 m 个任务都完成时,工作完成. 现在可以把任意一个边的边权变为 ...
- 【UOJ #150】【NOIP 2015】运输计划
http://uoj.ac/problem/150 用树链剖分求lca,二分答案树上差分判断. 时间复杂度$O(nlogn)$,n,m同阶. #include<cstdio> #inclu ...
- NOIP2015 D2T3 运输计划
拿到题目的第一眼 首先这是一棵n个节点的树(别说你看不出来) 然后对于树上的m条链我们可以选取树上的唯一一条边使它的边权变为0 求处理后最长链的长度 20分 m=1好啦,好像可做一眼望去全是水 只需求 ...
- cogs 2109. [NOIP 2015] 运输计划 提高组Day2T3 树链剖分求LCA 二分答案 差分
2109. [NOIP 2015] 运输计划 ★★★☆ 输入文件:transport.in 输出文件:transport.out 简单对比时间限制:3 s 内存限制:256 MB [题 ...
- 4632 NOIP[2015] 运输计划
4632 NOIP[2015] 运输计划 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 大师 Master 题解 题目描述 Description 公元 2044 ...
- 【数据结构】运输计划 NOIP2015提高组D2T3
[数据结构]运输计划 NOIP2015提高组D2T3 >>>>题目 [题目描述] 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航 ...
- [NOIP 2015]运输计划-[树上差分+二分答案]-解题报告
[NOIP 2015]运输计划 题面: A[NOIP2015 Day2]运输计划 时间限制 : 20000 MS 空间限制 : 262144 KB 问题描述 公元 2044 年,人类进入了宇宙纪元. ...
- Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)
Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...
- NOIP 2015 BZOJ 4326 运输计划 (树链剖分+二分)
Description 公元 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n− 条双向航道,每条航道建立在两个星球之间,这 n− 条航道连通了 L 国的所有星球. 小 P 掌管一家物流公司, ...
随机推荐
- Highlight.js语法突出显示
正如我在这个博客开始之前所说的最小可行产品,因此我在几个小时内就开始运行了.这种方法在初始推动之后会减慢你的速度.最新的例子是要提供语法高亮的代码片段. 规格由于使用静态网站生成器,我的狩猎的开始立即 ...
- POJ 3693 Maximum repetition substring(连续重复子串)
http://poj.org/problem?id=3693 题意:给定一个字符串,求重复次数最多的连续重复子串. 思路: 这道题确实是搞了很久,首先枚举连续子串的长度L,那么子串肯定包含了r[k], ...
- Java的反射机制Reflect
简介: 动态获取类的信息.动态调用对象的方法的功能叫做:Java 的反射(Reflection)机制. Reflection是不同于C++等静态语言,而被视为准动态语言的关键性质.反射机制允许程序在运 ...
- 【Java】【异常】
java中2种方法处理异常:1.在发⽣异常的地方直接处理:2.将异常抛给调用者,让调⽤者处理.异常分类1.检查性异常: java.lang.Exception2.运⾏期异常: java.lang.Ru ...
- Money 20/20 | 未来金融数字化转型:数字化半径与全栈式战略观
小蚂蚁说: 近年来,国际和国内的领先银行纷纷全力投入数字化转型.IDC去年报告说,全球1000大企业里面,67%已经把数字化转型定为企业级战略,而决定数字化转型成功与否的是人的思想改变.我们用数字化半 ...
- "ProgrammerHome"项目笔记
系统目的: 1.技术练习:把平时不用的,重要技术栈,在此项目中打磨(java.python.算法.系统构架) 2.新技术(工具)应用:有些平时想做,想实现的技术,可以在这里实现.而且以微服务的方式,轻 ...
- Error: Program type already present: okhttp3.Authenticator$1
在app中的build.gradle中加入如下代码, configurations { all*.exclude group: 'com.google.code.gson' all*.exclude ...
- 《剑指offer》第五十三题(0到n-1中缺失的数字)
// 面试题53(二):0到n-1中缺失的数字 // 题目:一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字 // 都在范围0到n-1之内.在范围0到n-1的n个数字中有且只有一个数 ...
- LeetCode--458--可怜的小猪
问题描述: 有1000只水桶,其中有且只有一桶装的含有毒药,其余装的都是水.它们从外观看起来都一样.如果小猪喝了毒药,它会在15分钟内死去. 问题来了,如果需要你在一小时内,弄清楚哪只水桶含有毒药,你 ...
- centOS 6.5采用python+nginx+uwsgi实现爬金十财经日历
上一篇中有关于安装nginx.python.uwsgi的过程,这里不再重述.下面是有关在具体布署中的一些过程和问题处理 一.因为用到了bs4(BeautifulSoup)\paste\lxml所以这些 ...