[luogu4886] 快递员(点分治,树链剖分,lca)
dwq推的火题啊.
这题应该不算是点分治,但是用的点分治的思想.
每次找重心,算出每一对询问的答案找到答案最大值,考虑移动答案点,使得最大值减小.
由于这些点一定不能在u的两颗不同的子树里,否则你怎么移动都不会使得答案更优.
于是答案点就只会往一棵子树里移动.
移动答案点的时候用找重心来跳保证时间复杂度.
求lca可以用树剖.
注释很详细.
// luogu-judger-enable-o2
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define maxn 100005
#define inf 1e9
using namespace std;
int n,m,rmx,size,ans,root,p;
int fa[maxn],siz[maxn],sz[maxn],top[maxn],dfn[maxn],dis[maxn];
int son[maxn],a[maxn],b[maxn],vis[maxn],dep[maxn],st[maxn];
int head[maxn],nxt[maxn<<1],to[maxn<<1],w[maxn<<1],cnt;
void add(int u,int v,int ww)
{
nxt[++cnt]=head[u];head[u]=cnt;
to[cnt]=v;w[cnt]=ww;
}
void getroot(int u,int ff)
{
sz[u]=1;int mx=0;
for(int i=head[u];i;i=nxt[i])
{
int v=to[i];
if(vis[v]||v==ff)continue;
getroot(v,u);sz[u]+=sz[v];
mx=max(mx,sz[v]);
}
mx=max(size-sz[u],mx);
if(mx<rmx)root=u,rmx=mx;
}
void dfs1(int u,int ff)
{
son[u]=0;fa[u]=ff;siz[u]=1;dep[u]=dep[ff]+1;
for(int i=head[u];i;i=nxt[i])
{
int v=to[i];if(v==ff)continue;
dis[v]=dis[u]+w[i];
dfs1(v,u);siz[u]+=siz[v];
if(siz[son[u]]<siz[v])son[u]=v;
}
}
void dfs2(int u,int tf)
{
dfn[u]=++p;top[u]=tf;
if(!son[u])return;dfs2(son[u],tf);
for(int i=head[u];i;i=nxt[i])
if(to[i]!=fa[u]&&son[u]!=to[i])dfs2(to[i],to[i]);
}
int getlca(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return (dep[x]<dep[y])?x:y;
}
void solve(int u)
{
if(vis[u])return;vis[u]=1;
int mx=0,k,tot=0;
fa[u]=p=dis[u]=0;dfs1(u,0);dfs2(u,u);//树链剖分,记得初始化树剖的变量
for(int i=1;i<=m;i++)mx=max(mx,dis[a[i]]+dis[b[i]]);//找答案最大值
ans=min(ans,mx);//由于往下一个重心跳答案不一定最优,所以一路都要对答案取min
for(int i=1;i<=m;i++)//多个最大值存到数组中
if(mx==dis[a[i]]+dis[b[i]])
{
//cout<<a[i]<<" "<<b[i]<<" "<<getlca(a[i],b[i])<<endl;
if(getlca(a[i],b[i])==u)return;
//如果询问点对的两个点在不同子树,那么无论往哪个方向移动答案点,答案都不会更优
st[++tot]=dfn[a[i]];//a,b一定在一个子树内,只加入一个即可
}
for(int i=head[u],v;i;i=nxt[i])//找到第一对点询问所在的子树
if(st[1]>=dfn[v=to[i]]&&st[1]<dfn[v]+siz[v])k=v;
for(int i=2;i<=tot;i++)//如果不在同一子树,当前点就是答案,因为你不能往任意一棵子树靠近
if(st[i]<dfn[k]||st[i]>dfn[k]+siz[k]-1)return;
size=sz[k];rmx=sz[k]+1;getroot(k,0);solve(root);
}
int main()
{
cin>>n>>m;ans=inf;
for(int i=1,u,v,ww;i<n;i++)
scanf("%d%d%d",&u,&v,&ww),add(u,v,ww),add(v,u,ww);
for(int i=1;i<=m;i++)scanf("%d%d",&a[i],&b[i]);
size=n;rmx=n+1;getroot(1,0);solve(root);
printf("%d\n",ans);
return 0;
}
[luogu4886] 快递员(点分治,树链剖分,lca)的更多相关文章
- 树分治&树链剖分相关题目讨论
预备知识 树分治,树链剖分 poj1741 •一棵有n个节点的树,节点之间的边有长度.方方方想知道,有多少个点对距离不超过m 题解 点分治模板题.详见我早上写的http://www.cnblogs ...
- CodeForces 916E Jamie and Tree(树链剖分+LCA)
To your surprise, Jamie is the final boss! Ehehehe. Jamie has given you a tree with n vertices, numb ...
- NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
原文链接https://www.cnblogs.com/zhouzhendong/p/9275606.html 题目传送门 - 洛谷P1600 题目传送门 - LOJ#2359 题目传送门 - Vij ...
- 【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)
题目 传送门:QWQ 分析 先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug.手写栈) 然后去学了学正解 核心挺好理解的,$ query(a) $是$ a $到根的异或和. 答案就是$ l ...
- POJ - 2763 Housewife Wind (树链剖分/ LCA+RMQ+树状数组)
题意:有一棵树,每条边给定初始权值.一个人从s点出发.支持两种操作:修改一条边的权值:求从当前位置到点u的最短路径. 分析:就是在边可以修改的情况下求树上最短路.如果不带修改的话,用RMQ预处理LCA ...
- BZOJ 3083 遥远的国度(树链剖分+LCA)
Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...
- cogs 186. [USACO Oct08] 牧场旅行 树链剖分 LCA
186. [USACO Oct08] 牧场旅行 ★★☆ 输入文件:pwalk.in 输出文件:pwalk.out 逐字节对比时间限制:1 s 内存限制:128 MB n个被自然地编号为 ...
- 【NOIP 2015 DAY2 T3】 运输计划 (树链剖分-LCA)
题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...
- Bzoj 2588 Spoj 10628. Count on a tree(树链剖分LCA+主席树)
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MB Description 给定一棵N个节点的树,每个点 ...
随机推荐
- MyBatis where、set、trim标签的用法
<!-- 4.3.1 where用法 <where>标签的作用:如果该便签包含的元素中有返回值,就插入一个where:如果 where后面的字符串是一and或or开头的,就将它们剔除 ...
- 详叙BeanWrapper和PropertyDescriptor
每篇一句 千古以来要饭的没有要早饭的,知道为什么吗? 相关阅读 [小家Spring]聊聊Spring中的数据转换:Converter.ConversionService.TypeConverter.P ...
- 【二分讲解及例题】火车站台连锁店-C++
首先我们先来从一个小游戏理解一下二分.(摘自程序员小灰的博客) 为什么说这样效率最高呢?因为每一次选择数字,无论偏大还是偏小,都可以让剩下的选择范围缩小一半. 给定范围0到1000的整数: 第一次我们 ...
- npm-472错误
今天无聊给npm进行了一波升级,却没想到导致出现bug,搞了半天才解决了....这里进行一下分享 1.安装npm npm install -g 升级到最新版npm install -g npm@< ...
- Unity3D 学习笔记一
安装Unity3D 环境 1 进入Unity3D 官网 http://unity3d.com/cn/ 找到获取 Unity 进去之后点击下载 2.下载完成之后进行安装,由于新的版本采用在线安装方式所以 ...
- 黑羽压测 比 jmeter、locust、loadrunner 更简便,性能更强
视频讲解 点击下方链接,观看 讲解视频 https://www.bilibili.com/video/av60089015/ 动机 目前市场上对API接口做性能测试工具有 Jmeter.LoadRun ...
- 鸽巢原理及其扩展——Ramsey定理
第一部分:鸽巢原理 咕咕咕!!! 然鹅大家还是最熟悉我→ a数组:but 我也很重要 $:我好像也出现不少次 以上纯属灌水 文章简叙:鸽巢原理对初赛时的问题求解以及复赛的数论题目都有启发意义.直接的初 ...
- 15号作品teamfinal使用体验
通过使用这款软件,可以轻松的查阅所处学期的任意周中某一天中的基教.一教.二教.三教和土木楼中的空教室,方便了同学去寻找空教室的方便,方便同学们上自习,节省寻找教室的时间,提供了非常大的便利. 打开界面 ...
- Android问题解决
1.clean之后R文件消失 clean之后R文件消失是因为布局的XML文件存在错误,无法编译你的资源文件,所以无法自动生成R文件,在Problem.LogCat等界面查看错误的原因,把错误改正即可: ...
- 深入理解 JavaScript 单例模式 (Singleton Pattern)
概念 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对象的类必须保证只有一个实例存在. 核心:确保只有一个实例,并提供全局访问. 实现思路 一个类能返回对象一个引用(永远是同 ...