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. 【Netty】使用解码器Decoder解决TCP粘包和拆包问题

    解码器Decoder和ChannelHandler的关系 netty的解码器通常是继承自ByteToMessageDecoder,而它又是继承自ChannelInboundHandlerAdapter ...

  2. 使用FastReport.net 报表在网页上实现打印功能

    这些年的工作当中,最早是在8年前接触到FastReport这个报表工具,从名字上来看,直译过来就是快速报表,正所谓天下武功,唯快不破,FastReport报表早些年确实是制作报表的不二之选,8年前的工 ...

  3. idea新建javaweb工程

    最近尝试了idea的使用,将idea建立javaweb工程的步骤记录下来 1.方框里边是重点 2.next后输入工程文件名点击finish 3.如图看到项目文件夹里边没有WEB-INF文件夹及里边的w ...

  4. Go语言圣经习题练习_1.5. 获取URL

    练习 1.7: 函数调用io.Copy(dst, src)会从src中读取内容,并将读到的结果写入到dst中,使用这个函数替代掉例子中的ioutil.ReadAll来拷贝响应结构体到os.Stdout ...

  5. 深入理解Java中的锁(三)

    ReadWriteLock接口 读写锁维护一对关联锁,一个只用于读操作,一个只用于写操作.读锁可以由多个线程同时持有,又称共享锁.写锁同一时间只能由一个线程持有,又称互斥锁.同一时间,两把锁不能被不同 ...

  6. 15款好用超赞的chrome插件, 开发者们的必备~

    今天推荐一波Chrome插件干货.这些插件带给我开发效率上的提升.所以在这里整理一下,分享给朋友们. 作为一名程序开发者,推荐一波常用的chrome插件,用了就舍不得丢,包括免费FQ工具,github ...

  7. 史上最全存储引擎、索引使用及SQL优化的实践

    史上最全存储引擎.索引使用及SQL优化的实践 1 MySQL的体系结构概述 2. 存储引擎 2.1 存储引擎概述 2.2 各种存储引擎特性 2.2.1 InnoDB 2.2.2 MyISAM 3. 优 ...

  8. 非web下的PowerMockito单元测试

    一.介绍 PowerMockito 可以用来 Mock 掉 final 方法(变量).静态方法(变量).私有方法(变量).想要使用 PowerMockito Mock掉这些内容,需要在编写的测试类上使 ...

  9. 二、Markdown基本语法

    目录 2.1 标题 一级标题 二级标题 三级标题 2.2 加粗 2.3倾斜 2.4 高亮 2.5 上标 2.6 下标 2.7 代码引用(>式) 2.8 代码引用(```式) 2.9 代码引入(` ...

  10. java8-流的操作

    流的操作 流的使用一般包括三件事: 一个数据源来执行一个查询; 一个中间操作链,形成一条流的流水线; 一个终端操作,执行流水线,并能生成结果 中间操作 操作 类型 返回类型 操作参数 函数描述符 fi ...