洛谷P2680 运输计划——树上差分
题目:https://www.luogu.org/problemnew/show/P2680
久违地1A了好高兴啊!
首先,要最大值最小,很容易想到二分;
判断当前的 mid 是否可行,需要看看有没有去掉一条边使满足的方案;
这就需要树上差分来找出每条边被几个超过 mid 的路线覆盖;
若有一条边正好被所有超过 mid 的路线覆盖,且去掉它之后最大的路线也能满足,就是可行的。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=3e5+;
int n,m,head[maxn],ct,cnt,st[maxn],ed[maxn],tag[maxn],lca[maxn],len[maxn];
int h[maxn],ans,mx,f[maxn][],dep[maxn],l,r,mid;
bool flag;
struct N{
int to,next,w;
N(int t=,int n=,int w=):to(t),next(n),w(w) {}
}edge[maxn<<];
void add(int x,int y,int z){edge[++ct]=N(y,head[x],z); head[x]=ct;}
void init(int x,int fa)
{
f[x][]=fa; dep[x]=dep[fa]+;
for(int i=;i<=;i++)f[x][i]=f[f[x][i-]][i-];
for(int i=head[x],u;i;i=edge[i].next)
if((u=edge[i].to)!=fa) h[u]=h[x]+edge[i].w, init(u,x);
}
int LCA(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
int k=dep[x]-dep[y];
for(int i=;i<=;i++)
if(k&(<<i))x=f[x][i];
for(int i=;i>=;i--)
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
if(x==y)return x;
return f[x][];
}
void dfs(int x)
{
for(int i=head[x],u;i;i=edge[i].next)
{
if((u=edge[i].to)==f[x][])continue;
dfs(u); if(flag)return;
if(tag[u]==cnt && mx-edge[i].w<=mid)flag=;
tag[x]+=tag[u];
}
}
bool ck()
{
cnt=; flag=;
memset(tag,,sizeof tag);
for(int i=;i<=m;i++)
if(len[i]>mid)
{
tag[st[i]]++; tag[ed[i]]++;
tag[lca[i]]-=; cnt++;
}
dfs();
return flag;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,x,y,z;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
init(,);
for(int i=;i<=m;i++)
{
scanf("%d%d",&st[i],&ed[i]);
lca[i]=LCA(st[i],ed[i]);
len[i]=h[st[i]]+h[ed[i]]-*h[lca[i]];
mx=max(mx,len[i]);
}
l=,r=mx;
while(l<=r)
{
mid=(l+r)>>;
if(ck())ans=mid,r=mid-;
else l=mid+;
}
printf("%d",ans);
return ;
}
洛谷P2680 运输计划——树上差分的更多相关文章
- 洛谷 P2680 运输计划-二分+树上差分(边权覆盖)
P2680 运输计划 题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条 ...
- 洛谷 P2680 运输计划 解题报告
P2680 运输计划 题目背景 公元2044年,人类进入了宇宙纪元. 题目描述 公元2044年,人类进入了宇宙纪元. \(L\)国有\(n\)个星球,还有\(n-1\)条双向航道,每条航道建立在两个星 ...
- 洛谷P2680 运输计划 [LCA,树上差分,二分答案]
题目传送门 运输计划 Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n?1 条双向航道,每条航道建立在两个星球之间, 这 n?1 条航道连通了 L 国的所 ...
- 洛谷P2680 运输计划(树上差分+二分)
传送门 考虑树上乱搞 首先这是满足二分性质的,如果在某个时间可以完成工作那么比他更长的时间肯定也能完成工作 然后考虑二分,设当前答案为$mid$,如果有一条链的长度大于$mid$,那么这条链上必须得删 ...
- 洛谷P2680 运输计划(倍增LCA + 树上差分 + 二分答案)
[题目链接] [思路]: 根据题意可以明显看出,当所有任务都完成时的时间是最终的结果,也就是说本题要求,求出最小的最大值. 那这样的话就暗示了将答案二分,进行check. [check方法]: 如果说 ...
- 洛谷 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 运输计划
大概就是二分+树上差分... 题意:给你树上m条路径,你要把一条边权变为0,使最长的路径最短. 最大的最小,看出二分(事实上我并没有看出来...) 然后二分k,对于所有大于k的边,树上差分求出最长公共 ...
随机推荐
- Linux的发展史和centos7的安装
目 录 第1章 Linux系统介绍与环境搭建准备UNIX操作系统 1 1.1 Unix的发展 1 1.2 MINIX的发展 1 1.3 GUN 1 1.4 Linux的 ...
- Buffer.from(arrayBuffer[, byteOffset[, length]])
Buffer.from(arrayBuffer[, byteOffset[, length]]) arrayBuffer - 一个 TypedArray 或 new ArrayBuffer() 的 . ...
- c++基础_字符串对比
#include <iostream> #include <string.h> #include <algorithm> using namespace std; ...
- UVa 11998 破碎的键盘(数组实现链表)
题意: 输入一行字符,其中包含'[' 和 ‘]’, 意思为键盘上的home 和 end 键, 然后模拟字符在键盘上输入. 输入一行最终的结果 分析: 用数组模拟一个链表, 在链表的头尾插入字母然后输出 ...
- this关键字的由来及使用
Student.java /* * 学生类 * * 起名字我们要求做到见名知意. * * 如果有局部变量名和成员变量名相同,在局部使用的时候,采用的是就近原则. * *我们有没有办法吧局部变量的nam ...
- java项目连接access数据库
1.导入Access_JDBC30.jar到项目中 jar包百度云链接:https://pan.baidu.com/s/10HFM3HomMArvfHjklA_1MA 密码:0qxp 项目名称-> ...
- JavaEE JDBC 补充注意点
JDBC补充注意点 @author ixenos 1.一个Statement对象可以用于多个不相关的命令和查询,但是一个Statement对象最多只能有一个打开的结果集,如果需要同时执行多个查询同时分 ...
- 添物不花钱学JavaEE(基础篇)- Servlet
Servlet是Java Web开发必须要掌握的. Servlet是什么? A servlet is a Java technology based web component, managed by ...
- [ C语言 ] 迷宫 迷宫生成器 [ 递归与搜索 ]
[原创]转载请注明出处 [浙江大学 程序设计专题] [地图求解器] 本题目要求输入一个迷宫地图,输出从起点到终点的路线. 基本思路是从起点(Sx,Sy)每次枚举该格子上下左右四个方向,直到走到终点(T ...
- 修改xampp的mysql默认密码
MySQL 的“root”用户默认状态是没有密码的,所以在 PHP 中您可以使用 mysql_connect("localhost","root"," ...