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)的更多相关文章

  1. 树分治&树链剖分相关题目讨论

    预备知识 树分治,树链剖分   poj1741 •一棵有n个节点的树,节点之间的边有长度.方方方想知道,有多少个点对距离不超过m 题解 点分治模板题.详见我早上写的http://www.cnblogs ...

  2. 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 ...

  3. NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分

    原文链接https://www.cnblogs.com/zhouzhendong/p/9275606.html 题目传送门 - 洛谷P1600 题目传送门 - LOJ#2359 题目传送门 - Vij ...

  4. 【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)

    题目 传送门:QWQ 分析 先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug.手写栈) 然后去学了学正解 核心挺好理解的,$ query(a) $是$ a $到根的异或和. 答案就是$ l ...

  5. POJ - 2763 Housewife Wind (树链剖分/ LCA+RMQ+树状数组)

    题意:有一棵树,每条边给定初始权值.一个人从s点出发.支持两种操作:修改一条边的权值:求从当前位置到点u的最短路径. 分析:就是在边可以修改的情况下求树上最短路.如果不带修改的话,用RMQ预处理LCA ...

  6. BZOJ 3083 遥远的国度(树链剖分+LCA)

    Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...

  7. cogs 186. [USACO Oct08] 牧场旅行 树链剖分 LCA

    186. [USACO Oct08] 牧场旅行 ★★☆   输入文件:pwalk.in   输出文件:pwalk.out   逐字节对比时间限制:1 s   内存限制:128 MB n个被自然地编号为 ...

  8. 【NOIP 2015 DAY2 T3】 运输计划 (树链剖分-LCA)

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

  9. 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个节点的树,每个点 ...

随机推荐

  1. Zeppelin 0.6.2使用Spark的yarn-client模式

    Zeppelin版本0.6.2 1. Export SPARK_HOME In conf/zeppelin-env.sh, export SPARK_HOME environment variable ...

  2. py+selenium 自动判断页面是否报错并显示在自动化测试报告【原创】

    有需求就会去研究解决的路子. 现在需求就是,测试报告报错信息一堆,但却无法肉眼看出是什么问题,你只能知道定位不到元素或是超时,但你却不知道其实进入页面就报错了或是提交表单就报错了!也就是看到报错,需要 ...

  3. 新手小白快速登天日记之安装python以及环境变量和pycharm解释器较为详细教程

    Python解释器安装及环境变量配置 Python官方网站:www.python.org 首先打开这个网址,找到downloads选择,因为我是Windows所以下载windows的,因电脑而异 然后 ...

  4. Minikube安装成功Kubernetes,一次过!

    介绍 Minikube 是 K8S 官方为了开发者能在个人电脑上运行 K8S 而提供的一套工具.实现上是通过 Go 语言编写,通过调用虚拟化管理程序,创建出一个运行在虚拟机内的单节点集群. 注:从这里 ...

  5. C# backgroundwork的使用方法

    引言:在 WinForms 中,有时要执行耗时的操作,在该操作未完成之前操作用户界面,会导致用户界面停止响应.解决的方法就是新开一个线程,把耗时的操作放到线程中执行,这样就可以在用户界面上进行其它操作 ...

  6. leetcode 48 矩阵旋转可以这么简单

    一行代码解决矩阵旋转(方法三). 方法1: 坐标法 def rotate(self, matrix): n = len(matrix) # 求出矩阵长度 m = (n + 1) // 2 # 求出层数 ...

  7. 转 python - Python在终端通过pip安装好包以后,在Pycharm中依然无法使用的解决办法

    转 https://blog.csdn.net/kouyi5627/article/details/80531442 在终端通过pip装好包以后,在pycharm中导入包时,依然会报错.新手不知道具体 ...

  8. java - 多态实现机制

    Java提供了编译时多态和运行时多态两种多态机制.前者是通过方法重载实现的,后者是通过方法的覆盖实现的. 在方法覆盖中,子类可以覆盖父类的方法,因此同类的方法会在父类与子类中有着不同的表现形式. 在J ...

  9. PLSQL连接数据库报监听程序找不到符合协议堆

    服务器上某个数据库出现' ORA-12516: TNS: 监听程序找不到符合协议堆栈要求的可用处理程'错误,要解决该问题首先查看一下数据库现有的进程数,是否已经达到参数processes的大小   根 ...

  10. [转]jQuery不同版本区别

    原文转载自csdn:http://blog.csdn.net/u010167032/article/details/23666145 了解不同版本之间的差异,与助于选择适合自己项目的版本. ⒈4重要新 ...