【数据结构】运输计划 NOIP2015提高组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 的物流公司完成阶段性工作所需要的最短时间是多少?

【输入描述】
第一行包括两个正整数 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

【输出描述】
输出文件只包含一个整数,表示小 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 条航道改造成虫洞: 则三个计划耗时分别为:11,12,11,故需要花费的时间为 12。

将第 2 条航道改造成虫洞: 则三个计划耗时分别为:7,15,11,故需要花费的时间为 15。

将第 3 条航道改造成虫洞: 则三个计划耗时分别为:4,8,11,故需要花费的时间为 11。

将第 4 条航道改造成虫洞: 则三个计划耗时分别为:11,15,5,故需要花费的时间为 15。

将第 5 条航道改造成虫洞: 则三个计划耗时分别为:11,10,6,故需要花费的时间为 11。

故将第 3 条或第 5 条航道改造成虫洞均可使得完成阶段性工作的耗时最短,需要花费的时间为 11。

>>>>分析

此题必备技能: 二分+树上差分+LCA

本题思路:

二分查找,check里面记录所有权值大于mid的路径,并求出这样的路径的数量(用cnt表示)

在这个过程中,求出所有路径”与mid的差“的最大值,就是最大超出的时间(用ans表示)

再找出一条能覆盖所有“大于mid的路径“的边,即为题目描述的虫洞

{

如果没有这样的边,那么不管怎样减总有至少一个任务的时间超过mid ,return false;

如果有这样的边,

{

for(每一条边)

如果(这条边被每一条大于mid的路径经过&&这条边权值大于ans)  也就是说减去这条边可以将每一条大于mid的路径减到mid下

return true;

}
}

具体分析:

(1)二分 :更多时间能完成任务,那么更短时间也能完成,具有单调性。

(2)树上差分:

tmp[i]表示:表示i这个点通往父亲的边,记录这条边被遍历的次数

num[i]表示:以i为根节点所有子树的tmp值

dis[i]表示:i 到根的距离

对于每一条链s(起点),t(终点),将s,t的tmp值+1;,将LCA(s,t)的tmp值-2

一个点最终被覆盖的次数就是这个点的num值(用dfs序维护)

(3)求LCA:  我这里选择的是倍增求LCA,真的是模板yo

(4)预处理:预处理出每一条链的链长和每一条链的LCA(这个说法好像不大对)

>>>>代码

#include<bits/stdc++.h>
#define maxn 300005
using namespace std;
int len=-,sum=-;
int n,m,tot,times;
int head[maxn],to[*maxn],nxt[*maxn],val[*maxn];
int dep[maxn],dis[maxn],fa[maxn][],tmp[maxn],id[maxn];
struct node
{
int u,v,lc,d;
}ed[maxn];
void read(int &x)
{
x=;int f=;char s=getchar();
while(s<''||s>''){if(s=='-') f=-;s=getchar();}
while(s>=''&&s<=''){x=x*+s-'';s=getchar();}x=x*f;
}
void add(int u,int v,int p)//前向星存双向边
{
to[++tot]=v;
nxt[tot]=head[u];
val[tot]=p;
head[u]=tot;
}
int lca(int x,int y)//倍增求lca
{
if(dep[x]<dep[y]) swap(x,y);//保证x在更深的地方
for(int i=;i>=;--i)
if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if(x==y) return x;
for(int i=;i>=;--i)//两个一起往上跳
{
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
}
return fa[x][];
}
void dfs(int u,int father)
{
id[++times]=u;//dfs序
for(int i=;i<=;++i) fa[u][i]=fa[fa[u][i-]][i-];//预处理倍增数组
for(int i=head[u];i;i=nxt[i])
{
int v=to[i];
if(v==father) continue;
fa[v][]=u;
dis[v]=dis[u]+val[i];
dep[v]=dep[u]+;
dfs(v,u);
}
}
bool check(int mid)
{
int cnt=,ans=-;
memset(tmp,,sizeof(tmp));
for(int i=;i<=m;++i)
{
if(ed[i].d>mid)
{
tmp[ed[i].u]++;//点到父亲边的出现次数
tmp[ed[i].v]++;
tmp[ed[i].lc]-=;
ans=max(ans,ed[i].d-mid);//找到“最大超出时限”
cnt++;
}
}
if(cnt==) return true;//所有边都小于mid
for(int i=n;i>=;--i) tmp[fa[id[i]][]]+=tmp[id[i]];
//为什么要倒序?从更接近叶子节点的地方开始,更新父节点经过的次数
for(int i=;i<=n;++i) //见解析
if(tmp[i]==cnt&&dis[i]-dis[fa[i][]]>=ans) return true;
return false;
}
int find(int l,int r)
{
int ans;
while(l<=r)
{
int mid=(l+r)>>;
if(check(mid)) ans=mid,r=mid-;
else l=mid+;
}
return ans;
}
int main()
{
// freopen("transport.in","r",stdin);
// freopen("transport.out","w",stdout);
read(n),read(m);
for(int i=;i<=n-;++i)
{
int x,y,z;
read(x),read(y),read(z);
add(x,y,z),add(y,x,z);
sum=max(sum,z);
}
dis[]=; dep[]=;
dfs(,);
for(int i=;i<=m;++i)
{
read(ed[i].u),read(ed[i].v);
ed[i].lc=lca(ed[i].u,ed[i].v);
ed[i].d=dis[ed[i].u]+dis[ed[i].v]-*dis[ed[i].lc];//求u到v的链长
len=max(len,ed[i].d);
}
printf("%d\n",find(len-sum,len));//二分 所用最短时间
return ;/**/
}
/*
6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5
*/

戳这里

思路借鉴 洛谷大佬:@D_14134

完结撒花!

【数据结构】运输计划 NOIP2015提高组D2T3的更多相关文章

  1. 洛谷 P2680 运输计划(NOIP2015提高组)(BZOJ4326)

    题目背景 公元 \(2044\) 年,人类进入了宇宙纪元. 题目描述 公元\(2044\) 年,人类进入了宇宙纪元. L 国有 \(n\) 个星球,还有 \(n-1\) 条双向航道,每条航道建立在两个 ...

  2. NOIP2015 提高组] 运输计划

    码农题啊兄弟们. 随便考虑二分一下,然后发现要取一条满足性质的边. 被所有大于\(mid\)的路径都覆盖,取了之后能把他们都弄到小于\(mid\) 那就树上差分再处理一下. 写了\(180h\),老年 ...

  3. [NOIP2015 提高组] 运输计划题解

    题目链接:P2680 [NOIP2015 提高组] 运输计划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 看了好长时间题解才终于懂的,有关lca和二分答案的题解解释的不详细,一时 ...

  4. 【题解】NOIP2015提高组 复赛

    [题解]NOIP2015提高组 复赛 传送门: 神奇的幻方 \([P2615]\) 信息传递 \([P2661]\) 斗地主 \([P2668]\) 跳石头 \([P2678]\) 子串 \([P26 ...

  5. 洛谷 P2678 & [NOIP2015提高组] 跳石头

    题目链接 https://www.luogu.org/problemnew/show/P2678 题目背景 一年一度的“跳石头”比赛又要开始了! 题目描述 这项比赛将在一条笔直的河道中进行,河道中分布 ...

  6. 【二分查找】 跳石头NOIP2015提高组 D2T1

    [二分查找]跳石头NOIP2015提高组 D2T1 >>>>题目 [题目描述] 一年一度的“跳石头”比赛又要开始了! 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石 ...

  7. [NOIP2015] 提高组 洛谷P2615 神奇的幻方

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

  8. 洛谷-神奇的幻方-NOIP2015提高组复赛

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,--,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

  9. 刷题总结——子串(NOIP2015提高组)

    题目: 题目背景 NOIP2015 提高组 Day2 T2 题目描述 有两个仅包含小写英文字母的字符串 A 和 B .现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在 ...

随机推荐

  1. eclipse jpa 工具生成实体类

    1,配置数据库连接 打开eclipse, 选择数据库: 下一步,选择驱动包 根据自己的驱动包路径选择对应的驱动包: 2,配置jpa-tool 在项目上面右键->properties 点击ok,然 ...

  2. GALV_maptravel研究分析(2)

    本节地图:Gov's Mansion,Campsite,Yourmansion ++++++++++++++++++++华丽丽的分割线+++++++++++++++++++++++++++++++++ ...

  3. Oracle 11g 概述 chaper1

    关系模型 E-R 模型 范式 1.简述Oracle oracle 是1977  IBM 公司研发的一款强大的数据库软件. 2.关系型数据的基本理论 关系型数据库与数据库管理系统  1)数据库是因为有对 ...

  4. mika的模板库

    二分图最大匹配: 1.匈牙利算法:注意dfs中是dfs(c[w[i]]),搜索的是与之匹配的点. #include<cstdio> #include<cstring> ],w[ ...

  5. 【SparkStreaming学习之二】 SparkStreaming算子操作

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...

  6. 自定义域名访问本地WEB应用

    自定义域名访问本地WEB应用 本地安装了WEB服务端,怎样通过自定义域名方式实现从公网访问本地WEB应用? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动WEB服务端 默认安装的WEB ...

  7. LeetCode Weekly Contest 121

    上周因为感冒没有刷题,两个星期没有刷题,没手感了,思维也没有那么活跃了,只刷了一道,下个星期努力. 984. String Without AAA or BBB Given two integers  ...

  8. Flutter数据库Sqflite之增删改查

    Flutter数据库Sqflite之增删改查   简介 sqflite是Flutter的SQLite插件,支持iOS和Android,目前官方版本是sqflite1.1.3 sqflite插件地址:h ...

  9. ElasticSearch(十)Elasticsearch检索出的数据列表按字段匹配的优先顺序及搜索单词拼音一部分搜不到数据

    检索出的数据列表按字段匹配的优先顺序 一.举例 比如,发布一篇文章,文章包括基本的字段包括标题.发布时间.点击率.关键字.内容.当在页面中输入“教育”搜索关键词,会检索出指定字段包括“教育”的所有数据 ...

  10. 常用VIM插件配置

    airline 状态栏美化 除了airline本体还要下airline主题 和打过powerline补丁的字体 常用设置: set laststatus=2 " 总是显示状态栏 set no ...