题目链接

problem

一棵n个点带边权的树,有m个条路径。选择一条边,将其权值变为0,使得长度最长的路径长度最小。求该长度最小为多少。

solution

其实仔细一想并不难。

删除一条边会导致所有经过这条边的路径长度减少该边长度。所有没经过这条边的路径长度不变。

所以我们只需要知道没经过该边的路径中的长度最大值,以及经过该边的路径中长度最大值。

显然经过该边的路径长度最大值我们可以当做最长路径的最大值。

现在只要对于每条边都能够计算出没经过该边的路径长度最大值即可。

我们发现并不需要对于每条边都求出该值。

因为删除的边肯定位于最长路径上。

然后我们就把最长路径扯平。并对上面的边进行编号。

如图,对于\(S-T\)这条路径,会在删除\(1,4,5\)这三条边时产生贡献。所以我们只要用两个数组分别记录出前缀最大值和后缀最大值即可。

然后枚举删除的边,记录最优答案。

code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 300100,logN = 20;
ll read() {
ll x = 0,f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
struct node {
int u,v,nxt,w,bz;
}e[N << 1];
int head[N],ejs;
void add(int u,int v,int w) {
e[++ejs].v = v;e[ejs].u = u;e[ejs].nxt = head[u];head[u] = ejs;e[ejs].w = w;
} int id[N],cnt,dis[N]; int DFS(int u,int V,int fa) {
if(u == V) {
id[u] = ++cnt;return 1;
}
for(int i = head[u];i;i = e[i].nxt) {
int v = e[i].v;
if(v == fa) continue;
if(DFS(v,V,u)) {
id[u] = ++cnt;
e[i].bz = 1;
return 1;
}
}
return 0;
}
void mark(int u,int p) {
id[u] = p;
for(int i = head[u];i;i = e[i].nxt) {
int v = e[i].v;
if(id[v]) continue;
mark(v,p);
}
}
int lca[N][21],dep[N];
void get_lca(int u,int fa) {
dep[u] = dep[fa] + 1; for(int i = 1;i <= logN;++i) lca[u][i] = lca[lca[u][i - 1]][i - 1]; for(int i = head[u];i;i = e[i].nxt) {
int v = e[i].v;
if(v == fa) continue;
dis[v] = dis[u] + e[i].w;
lca[v][0] = u;
get_lca(v,u);
} }
int LCA(int x,int y) {
if(dep[x] < dep[y]) swap(x,y); for(int i = logN;i >= 0;--i)
if(dep[lca[x][i]] >= dep[y]) x = lca[x][i]; for(int i = logN;i >= 0;--i)
if(lca[x][i] != lca[y][i]) x = lca[x][i],y = lca[y][i]; if(x != y) return lca[x][0];
return x; }
int mx1[N],mx2[N];
struct QUE {
int s,t,len;
}Q[N];
int main() {
int mxx = 0;
int n = read(),m = read(); for(int i = 1;i < n;++i) {
int u = read(),v = read(),w = read();
add(u,v,w);add(v,u,w);
} get_lca(1,0); int S = 0,T = 0; for(int i = 1;i <= m;++i) {
Q[i].s = read();Q[i].t = read();
Q[i].len = dis[Q[i].s] + dis[Q[i].t] - dis[LCA(Q[i].s,Q[i].t)] * 2;
if(Q[i].len > mxx) {
mxx = Q[i].len;
S = Q[i].s;T = Q[i].t;
}
} DFS(S,T,0); for(int i = 1;i <= n;++i) {
if(id[i]) {
mark(i,id[i]);
}
} for(int i = 1;i <= m;++i) {
int s = Q[i].s,t = Q[i].t; int l = id[s],r = id[t];
if(l > r) swap(l,r); mx1[l - 1] = max(mx1[l - 1],Q[i].len);
mx2[r] = max(mx2[r],Q[i].len);
} for(int i = cnt;i >= 0;--i) {
mx1[i] = max(mx1[i],mx1[i + 1]);
}
for(int i = 1;i <= cnt;++i)
mx2[i] = max(mx2[i],mx2[i - 1]); int ans = 1e9; for(int i = 1;i <= ejs;++i) {
if(e[i].bz) {
int l = id[e[i].u],r = id[e[i].v];
if(l > r) swap(l,r); int k = max(max(mx1[l],mx2[l]),mxx - e[i].w); ans = min(ans,k);
}
} cout<<(ans == 1e9 ? 0 : ans); return 0;
}

Noip2015Day2T3 运输计划的更多相关文章

  1. Vijos1983 NOIP2015Day2T3 运输计划 transport LCA

    题目链接Vijos 题目链接UOJ 该博客在博客园的链接 转载一个大佬的题解: 点击这里->大佬题解 下面谈谈我的感悟: 当然写代码也是写的很艰辛: 我力劝C++的同胞们,这题卡常数,Dfs党会 ...

  2. NOIP2015Day2T3运输计划(二分+树上差分)

    做了这么多NOIPTG的题,这是唯一 一道一眼秒的T3(有时候T2还不会做QAQ)... 题目大意就不说了QWQ 思路大概是:啊最大值最小化,来个二分.检验mid的话,显然就是用最长路径减去所有边权& ...

  3. 运输计划NOIP2015Day2T3

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

  4. bzoj 4326: NOIP2015 运输计划

    4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个 ...

  5. noip2015 运输计划

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

  6. 【bzoj4326】[NOIP2015]运输计划

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

  7. [题解]vijos 运输计划

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

  8. NOIP2015 运输计划(bzoj4326)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 886  Solved: 574[Submit][Status] ...

  9. UOJ #150 【NOIP2015】 运输计划

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

随机推荐

  1. ES 6新语法

    一.块级作用域绑定 回顾:使用var关键字定义变量 定义 = 声明 + 赋值:   1. 可以一次定义多个变量 2. 定义时可以只声明不赋值 3. 定义之后可以随时修改变量的值 4. 变量声明会被提升 ...

  2. ES6-promise对象的使用

    Promise 的含义(摘自阮一峰ES6ru) Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一 ...

  3. Pluralsight 科技公司公布自己的avaScript 成为最受欢迎的开发技术

    根据 SDTimes 报道,Pluralsight 科技公司公布自己的 Technology Index,JavaScript 位居榜首. Pluralsight,是美国的一家面向软件开发者的在线教育 ...

  4. java中文件复制的4种方式

    今天一个同事问我文件复制的问题,他一个100M的文件复制的指定目录下竟然成了1G多,吓我一跳,后来看了他的代码发现是自己通过字节流复制的,定义的字节数组很大,导致复制后目标文件非常大,其实就是空行等一 ...

  5. tomcat启停脚本

    脚本存放目录 /etc/init.d/ #!/bin/bash # description: Tomcat8 Start Stop Restart # processname: tomcat8 # c ...

  6. Django中的sql注入

    Django中防止SQL注入的方法 方案一总是使用Django自带的数据库API.它会根据你所使用的数据库服务器(例如PostSQL或者MySQL)的转换规则,自动转义特殊的SQL参数.这被运用到了整 ...

  7. [考试反思]1110csp-s模拟测试108:消遣

    是套废题.T1题面错了,T2细节多而暴力>部分分,T3题目错了. T1:打表 题面应该是输出差值期望而不是答案值期望. 看到题目,果断打表. 答案就是所有值差之和除2的k次方. #include ...

  8. opencv-python图像二值化函数cv2.threshold函数详解及参数cv2.THRESH_OTSU使用

    cv2.threshold()函数的作用是将一幅灰度图二值化,基本用法如下: #ret:暂时就认为是设定的thresh阈值,mask:二值化的图像 ret,mask = cv2.threshold(i ...

  9. MySql索引背后的数据结构及算法

    本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree ...

  10. go语言之用户输入&类型别名&类型转换

    1.用户输入 package main import "fmt" func main() { //用户输入,程序接受并输出 var v1 int //fmt.Println(&qu ...