题目背景

公元 2044 年,人类进入了宇宙纪元。

题目描述

公元 2044 年,人类进入了宇宙纪元

L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间,这 n-1n−1 条航道连通了 LL 国的所有星球。

小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 u_iui​ 号星球沿最快的宇航路径飞行到 v_ivi​ 号星球去。显然,飞船驶过一条航道是需要时间的,对于航道 jj ,任意飞船驶过它所花费的时间为 t_jtj​ ,并且任意两艘飞船之间不会产生任何干扰。

为了鼓励科技创新, L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

在虫洞的建设完成前小 P 的物流公司就预接了 mm 个运输计划。在虫洞建设完成后,这 mm 个运输计划会同时开始,所有飞船一起出发。当这 mm 个运输计划都完成时,小 P 的物流公司的阶段性工作就完成了。

如果小 P 可以自由选择将哪一条航道改造成虫洞, 试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?

输入输出格式

输入格式:

第一行包括两个正整数 n, mn,m ,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 11 到 nn 编号。

接下来 n-1n−1 行描述航道的建设情况,其中第 ii 行包含三个整数 a_i, b_iai​,bi​ 和 t_iti​ ,表示第 ii 条双向航道修建在 a_iai​ 与 b_ibi​ 两个星球之间,任意飞船驶过它所花费的时间为 t_iti​ 。数据保证 1 \leq a_i,b_i \leq n1≤ai​,bi​≤n 且 0 \leq t_i \leq 10000≤ti​≤1000 。

接下来 mm 行描述运输计划的情况,其中第 jj 行包含两个正整数 u_juj​ 和 v_jvj​ ,表示第 jj 个运输计划是从 u_juj​ 号星球飞往 v_jvj​号星球。数据保证 1 \leq u_i,v_i \leq n1≤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

二分移动所需的时间,在二分出的时间里用树上倍增检验能否实现
看了题解还是调到吐血,最后发现m放在n后面直接读入了..
代码:
 #include<algorithm>
#include<cstdio>
#include<cstring> const int Maxv = ;
int Book[Maxv], Head[Maxv], f[Maxv][], st[Maxv][], Top[Maxv], Tdis[Maxv], q[Maxv], rnum, tail, cnt, n, m;
bool lea[Maxv], vis[Maxv], fs; struct Node{
int u, v, w, next;
}e[Maxv << ]; struct Army{
int Rest, Top;
}army[Maxv]; int read(){
int x = , f = ;
char ch = getchar();
while (ch < '' || ch > '') {
if (ch == '-') {
f = -;
}
ch = getchar();
}
while (ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x * f;
} void Add_Edge(int u, int v, int w){
cnt++;
e[cnt].v = v;
e[cnt].w = w;
e[cnt].next = Head[u];
Head[u] = cnt;
} void Add(int u, int v, int w){
Add_Edge(u, v, w);
Add_Edge(v, u, w);
} inline bool Cmp(int a, int b){
return a > b;
}
inline bool Cmpmin(Army a, Army b){
return a.Rest < b.Rest;
} inline bool Cmpmax(Army a, Army b){
return a.Rest > b.Rest;
} void dfs(int u, int father){
for (int i = Head[u]; i; i = e[i].next) {
int v = e[i].v;
if (v == father) {
continue;
}
f[v][] = u;
st[v][] = e[i].w;
dfs(v, u);
}
}//预处理倍增 void RMQ(){
for (int j = ; j <= ; j++) {
for (int i = ; i <= n; i++) {
f[i][j] = f[ f[i][j - ] ][j - ];
st[i][j] = st[i][j - ] + st[ f[i][j - ] ][j - ];
}
}
}//预处理倍增 void dfs1(int u, int father, int topf, int dist){
Top[u] = topf;
Tdis[u] = dist;
bool ft = false;
for (int i = Head[u]; i; i = e[i].next) {
int v = e[i].v;
if (v == father) {
continue;
}
ft = true;
dfs1(v, u, topf, dist);
}
if (!ft) {
lea[u] = true; //标记叶子节点
}
} void dfs2(int u, int father){
if (lea[u]) {
fs = true;
return;
}
for (int i = Head[u]; i; i = e[i].next) {
int v = e[i].v;
if (v == father) {
continue;
}
else if (vis[v]) {
continue;
}
dfs2(v, u);
if (fs) {
return;
}
}
} inline bool Look(int v){
fs = false;
dfs2(v, f[v][]);
return fs;
} inline bool judge(int mid){
memset(vis, false, sizeof(vis));
memset(q, , sizeof(q));
memset(army, , sizeof(army));
rnum = ;
tail = ;
for (int i = ; i <= m; i++) {
int tim = mid;
int now = Book[i];
bool syst = false;
while () {
for (int j = ; j >= ; j--) {
if (f[now][j] && st[now][j] <= tim) {
tim -= st[now][j];
now = f[now][j]; //向上跳
break;
}
if (j == || now == ) {
syst = true;
break; //停止条件
}
}
if (syst) {
break;
}
}
if (now == ) {
army[++rnum].Top = Top[ Book[i] ];
army[rnum].Rest = tim;
}
else {
vis[now] = true;
}
}
std::sort(army + , army + m + , Cmpmin);
for (int i = ; i <= m; i++) {
if (army[i].Rest < Tdis[ army[i].Top ]) {
if (!vis[ army[i].Top ] && Look(army[i].Top)) {
vis[ army[i].Top ] = true;
army[i].Rest = -;
}
}
}
std::sort(army + , army + m + , Cmpmax);
for (int i = Head[]; i; i = e[i].next) {
int v = e[i].v;
if (!vis[v] && Look(v)) {
q[++tail] = e[i].w;
}
}
std::sort(q + , q + tail + , Cmp);
for (int i = ; i <= tail; i++) {
if (army[i].Rest < q[i]) {
return false;
}
}
return true;
} int main(){
int u, v, w, R = , cnt1 = , Ans = ;
n = read(); for (int i = ; i < n; i++) {
u = read();
v = read();
w = read();
Add(u, v, w);
R += w;
}
dfs(, );
for (int i = Head[]; i; i = e[i].next) {
int v = e[i].v;
dfs1(v, , v, e[i].w);
}
RMQ();
m = read();
for (int i = ; i <= m; i++) {
Book[i] = read();
}
for (int i = Head[]; i; i = e[i].next) {
cnt1++;
}
if (cnt1 > m) {
printf("-1\n");
return ;
}
int L = ;
while (L <= R) {
int mid = (L + R) >> ;
if (judge(mid)) {
Ans = mid;
R = mid - ;
}
else {
L = mid + ;
}
}
printf("%d\n", Ans);
return ;
}
 

[树上倍增+二分答案][NOIP2012]运输计划的更多相关文章

  1. [NOIP 2015]运输计划-[树上差分+二分答案]-解题报告

    [NOIP 2015]运输计划 题面: A[NOIP2015 Day2]运输计划 时间限制 : 20000 MS 空间限制 : 262144 KB 问题描述 公元 2044 年,人类进入了宇宙纪元. ...

  2. NOIP2015 运输计划 (树上差分+二分答案)

    ---恢复内容开始--- 题目大意:给你一颗树,你可以把其中一条边的边权改成0,使给定的一些树链的权值和的最大值最小 把lenth定义为未修改边权时的答案 考虑二分答案,如果二分的答案成立,设修改成0 ...

  3. 洛谷P2680 运输计划(倍增LCA + 树上差分 + 二分答案)

    [题目链接] [思路]: 根据题意可以明显看出,当所有任务都完成时的时间是最终的结果,也就是说本题要求,求出最小的最大值. 那这样的话就暗示了将答案二分,进行check. [check方法]: 如果说 ...

  4. 字符串(tjoi2016,heoi2016,bzoj4556)(sam(后缀自动机)+线段树合并+倍增+二分答案)

    佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为\(n\)的字符串\(s\),和\(m\)个问题.佳媛姐姐必须正确回答这\(m\)个问题, ...

  5. BZOJ 2783 树 - 树上倍增 + 二分

    传送门 分析: 对每个点都进行一次二分:将该点作为链的底端,二分链顶端所在的深度,然后倍增找到此点,通过前缀和相减求出链的权值,并更新l,r. code #include<bits/stdc++ ...

  6. [NOIP2015] 提高组 洛谷P2680 运输计划

    题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...

  7. [NOIP2015]运输计划 线段树or差分二分

    目录 [NOIP2015]运输计划 链接 思路1 暴力数据结构 思路2 二分树上差分 总的 代码1 代码2 [NOIP2015]运输计划 链接 luogu 好久没写博客了,水一篇波. 思路1 暴力数据 ...

  8. 洛谷P1084 疫情控制 [noip2012] 贪心+树论+二分答案 (还有个小bugQAQ

    正解:贪心+倍增+二分答案 解题报告: 正好想做noip的题目然后又想落实学长之前讲的题?于是就找上了这题 其实之前做过,70,然后实在细节太多太复杂就不了了之,现在再看一遍感觉又一脸懵了... 从标 ...

  9. BZOJ4326或洛谷2680 运输计划

    BZOJ原题链接 洛谷原题链接 用\(LCA\)初始化出所有运输计划的原始时间,因为答案有单调性,所以二分答案,然后考虑检验答案. 很容易想到将所有超出当前二分的答案的运输计划所经过的路径标记,在这些 ...

随机推荐

  1. python--对象实例化过程

    实例化过程: class luffy_stu: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = ...

  2. (转)get和post的区别

    Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE.URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而HTTP ...

  3. Java解法-两数相加(Add Two Numbers)

    问题  给出两个非空的链表用来表示两个非负的整数.其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和. ...

  4. Vue相关文章

    1.新手向:Vue 2.0 的建议学习顺序 2.用webstorm搭建vue项目 3.vue-cli3.0项目结构

  5. 在Centos7上安装wxPython4.0.4

    在linux上安装wxPython4.0.4时需要gtk+2.0,在安装wxPython4.0.4遇到以下错误. linux上是用pip安装wxPython4.0.4的,执行命令如下: pip ins ...

  6. Python 3.7 安装Twisted

    win10电脑  64位系统 Python 3.7 版本安装Twisted-18.9.0-cp37-cp37m-win32.whl 会成功 先下载下来,放到 Scripts文件夹下 然后cmd 我的是 ...

  7. 一千行 MySQL 详细学习笔记

    Windows服务 -- 启动MySQL net start mysql -- 创建Windows服务 sc create mysql binPath= mysqld_bin_path(注意:等号与值 ...

  8. ExtJS4.2下将表单元素放在菜单时不能进行拷贝的问题解决办法

    通过浏览器F12我们发现,在菜单对应的dom元素上面,有几个系统附加的事件处理函数,只要我们将它去掉就可以了.示意代码如下: { xtype: "button", scope: z ...

  9. java调用webservice方法

    由于项目的历史原因,webservice服务端是乙方公司开发的,我们自己开发的系统需要去调用乙方公司的webservice接口.前面用了网上提供的一种方法(非生成代理类),怎么也调用不成功(也许是因为 ...

  10. 云笔记项目-Spring事务学习-传播NESTED

    接下来测试事务传播属性NESTED Service层 Service层方法事务传播属性都设置为NESTED. LayerT层代码 package LayerT; import javax.annota ...