BZOJ4326或洛谷2680 运输计划
BZOJ原题链接
洛谷原题链接
用\(LCA\)初始化出所有运输计划的原始时间,因为答案有单调性,所以二分答案,然后考虑检验答案。
很容易想到将所有超出当前二分的答案的运输计划所经过的路径标记,在这些运输计划都经过的边中的权值最大的这条边上建立虫洞,如果能使得所有运输计划中需要时间最多的那个计划能在当前二分的答案之内完成,那么这个答案就是可行的。
然后考虑如何快速找到这些运输计划都经过的边,本质上我们要求的就是一条边被覆盖几次,所以考虑树上差分。
定义\(dif[i]\)表示点\(i\)到它父亲节点的这条边被覆盖几次,对于一个计划\((x,y)\),我们将\(dif[x]++,dif[y]++,dif[LCA(x,y)]-2\),最后将点\(i\)的子树中所有的\(dif\)累加到\(dif[i]\)即可。
不过这题挺卡常的,所以要注意常数。
- 不在求\(LCA\)的同时求经过路径长度,而是用该表达式\(dis[x]+dis[y]-dis[LCA(x,y)]\times 2\)(\(dis[x]\)表示点\(x\)到根的距离)。
- 缩小二分答案的范围,上界定为最长链的长度,即所有运输计划中需要时间最多的那个计划,下界定为最长链减去这条链上权值最大的边。
- 计算\(dif\)不用\(dfs\),而是在初始化倍增\(LCA\)的时候求出时间戳,然后枚举时间戳来累加并判断。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 3e5 + 10;
const int M = 19;
struct ts {
int x, y, t, po;
};
ts a[N];
int fi[N], di[N << 1], ne[N << 1], da[N << 1], f[N][M], g[N], dif[N], dis[N], de[N], dfn[N], l, gn, n, m, ti;
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline void add(int x, int y, int z)
{
di[++l] = y;
da[l] = z;
ne[l] = fi[x];
fi[x] = l;
}
inline void sw(int &x, int &y)
{
int z = x;
x = y;
y = z;
}
inline int maxn(int x, int y)
{
return x > y ? x : y;
}
bool comp(ts x, ts y)
{
return x.t > y.t;
}
void dfs(int x)
{
int i, y;
dfn[++ti] = x;
for (i = 1; i <= gn; i++)
{
f[x][i] = f[f[x][i - 1]][i - 1];
if (!f[x][i])
break;
}
for (i = fi[x]; i; i = ne[i])
if ((y = di[i]) ^ f[x][0])
{
f[y][0] = x;
dis[y] = dis[x] + (g[y] = da[i]);
de[y] = de[x] + 1;
dfs(y);
}
}
int lca(int x, int y)
{
int i;
if (de[x] > de[y])
sw(x, y);
for (i = gn; ~i; i--)
if (de[f[y][i]] >= de[x])
y = f[y][i];
if (!(x ^ y))
return x;
for (i = gn; ~i; i--)
if (f[x][i] ^ f[y][i])
{
x = f[x][i];
y = f[y][i];
}
return f[x][0];
}
int fin(int x, int y, int z)
{
int ma = 0;
for (; x ^ z; x = f[x][0])
ma = maxn(ma, g[x]);
for (; y ^ z; y = f[y][0])
ma = maxn(ma, g[y]);
return ma;
}
bool judge(int mid)
{
int i, k = a[1].t - mid, o = 0, x;
memset(dif, 0, sizeof(dif));
for (i = 1; i <= m; i++)
{
if (a[i].t <= mid)
break;
dif[a[i].x]++;
dif[a[i].y]++;
dif[a[i].po] -= 2;
o++;
}
if (!o)
return true;
for (i = n; i; i--)
{
x = dfn[i];
dif[f[x][0]] += dif[x];
if (!(dif[x] ^ o) && g[x] >= k)
return true;
}
return false;
}
int main()
{
int i, x, y, z, l, r, mid;
n = re();
m = re();
for (i = 1; i < n; i++)
{
x = re();
y = re();
z = re();
add(x, y, z);
add(y, x, z);
}
gn = log2(n);
de[1] = 1;
dfs(1);
for (i = 1; i <= m; i++)
{
a[i].x = re();
a[i].y = re();
a[i].po = lca(a[i].x, a[i].y);
a[i].t = dis[a[i].x] + dis[a[i].y] - (dis[a[i].po] << 1);
}
sort(a + 1, a + m + 1, comp);
r = a[1].t;
l = r - fin(a[1].x, a[1].y, a[1].po);
while (l < r)
{
mid = (l + r) >> 1;
if (judge(mid))
r = mid;
else
l = mid + 1;
}
printf("%d", r);
return 0;
}
BZOJ4326或洛谷2680 运输计划的更多相关文章
- 洛谷 P2680 运输计划-二分+树上差分(边权覆盖)
P2680 运输计划 题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条 ...
- 洛谷 P2680 运输计划(NOIP2015提高组)(BZOJ4326)
题目背景 公元 \(2044\) 年,人类进入了宇宙纪元. 题目描述 公元\(2044\) 年,人类进入了宇宙纪元. L 国有 \(n\) 个星球,还有 \(n-1\) 条双向航道,每条航道建立在两个 ...
- 洛谷——P2680 运输计划
https://www.luogu.org/problem/show?pid=2680 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每 ...
- [NOIP2015] 提高组 洛谷P2680 运输计划
题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...
- 洛谷 P2680 运输计划 解题报告
P2680 运输计划 题目背景 公元2044年,人类进入了宇宙纪元. 题目描述 公元2044年,人类进入了宇宙纪元. \(L\)国有\(n\)个星球,还有\(n-1\)条双向航道,每条航道建立在两个星 ...
- 洛谷P2680 运输计划 [LCA,树上差分,二分答案]
题目传送门 运输计划 Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n?1 条双向航道,每条航道建立在两个星球之间, 这 n?1 条航道连通了 L 国的所 ...
- 洛谷 P2680 运输计划
题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...
- 洛谷P2680 运输计划
大概就是二分+树上差分... 题意:给你树上m条路径,你要把一条边权变为0,使最长的路径最短. 最大的最小,看出二分(事实上我并没有看出来...) 然后二分k,对于所有大于k的边,树上差分求出最长公共 ...
- 洛谷P2680运输计划
传送门啦 要求的就是,把树上的一条边的权值设为0之后,所有路径中的最大值的最小值. 首先二分最大值,假设某次二分的最大值为x,我们首先找出所有大于x的路径(也就是我们需要通过改权缩短的路径),并把路径 ...
随机推荐
- Android Studio: Application Installation Failed
[Android Studio: Application Installation Failed] 参考:http://stackoverflow.com/questions/32718044/and ...
- springboot jpa 审计
@SpringBootApplication @EnableJpaAuditing public class Application {...} @Component public class Aud ...
- OpenSessionInViewFilter 的配置及作用(原文地址: http://blog.csdn.net/sunsea08/article/details/4545186)
spring为我们解决hibernate的Session的关闭与开启问题. Hibernate 允许对关联对象.属性进行延迟加载,但是必须保证延迟加载的操作限于同一个 Hibernate Sessio ...
- Dedecms织梦内容页获取当前页面顶级栏目名称方法
Dedecms织梦做站的时候,需要在当前页面调用顶级栏目名称的时候,织梦默认{dede:field name='typename' /} 可以获取当前栏目页上一级栏目的名称,而不是当前栏目顶级栏目名称 ...
- eclipse启动tomcat后,无法通过路径访问项目
eclipse已启动,访问localhost:8080也出现了tomcat页面,但是无法通过项目路径去访问项目,解决办法: 在控制台区域打开tomcat server,默认是第一项,且无法修改: 先把 ...
- 最短路+叉积 poj1556
题目链接:The Doors - POJ 1556 - Virtual Judge https://vjudge.net/problem/POJ-1556 题意是叫我们计算从(0,5)到(10,5) ...
- android.support.v4与Android.support.v7
Android提供了android.support.v4和android.support.v7两个库,以便低版本API可以使用高版本API的功能. Fragment(碎片)类,是在Android 3. ...
- Mycat性能调优指南
本篇内容来自于网络 JVM调优: 内存占用分两部分:java堆内存+直接内存映射(DirectBuffer占用),建议堆内存 适度大小,直接映射内存尽可能大,两种一起占据操作系统的1/2-2/3的内存 ...
- 【mysql】字段支持JSON类型
mysql从5.7开始已经支持JSON类型的字段. 支持的操作:添加,修改,置空,子key添加,子key重置,子key删除,通过子key查找等. 但是这里和普通字段的修改和查找不同,涉及到一些JSON ...
- [剑指Offer]40-最小的k个数
题目链接 https://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf?tpId=13&tqId=11182&t ...