传送门


淀粉质好题啊qaq

我们先考虑随便选择一个点作为邮递中心,通过移动邮递中心找到更优的位置。将路径最大值求出,并将路径最大值对应的那一些路径拿出来考虑。可以知道,如果说这些路径中存在一条经过当前邮递中心的路径,意味着当前点就是最优的(因为不论邮递中心怎么移动,这一条路径的长度不会小于当前值,也就是说答案不会小于当前的最大值),所以只有起点和终点在同一子树内的路径的最长路径才有可能通过移动邮递中心使得答案变得更小。而如果说存在两条路径分布在不同子树内,显然也是无法通过移动使得答案更优的,因为不论邮递中心怎么移动,至少会有一条路径的长度增加。所以只有所有最长路径都在当前邮递中心的一棵子树内的时候,可以通过将邮递中心向子树内移动获得更优的答案。

但是显然每一次都移动一格的复杂度最坏是$O(nm)$的,我们考虑优化。我们可以借助于点分治的思想,每一次移动不是移动到子树的根的位置,而是跳到这一棵子树的重心的位置递归求解,这样的复杂度就是$O(mlogn)$了。

 #include<bits/stdc++.h>
//This code is written by Itst
using namespace std; inline int read(){
int a = ;
bool f = ;
char c = getchar();
while(c != EOF && !isdigit(c)){
if(c == '-')
f = ;
c = getchar();
}
while(c != EOF && isdigit(c)){
a = (a << ) + (a << ) + (c ^ '');
c = getchar();
}
return f ? -a : a;
} const int MAXN = ;
struct Edge{
int end , upEd , w;
}Ed[MAXN << ];
int head[MAXN] , query[MAXN][] , dis[MAXN] , size[MAXN] , be[MAXN];
int N , M , cntEd , ans , nowSize , minSize , minInd;
bool vis[MAXN]; inline void addEd(int a , int b , int c){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
Ed[cntEd].w = c;
head[a] = cntEd;
} void getSize(int now){
++nowSize;
vis[now] = ;
for(int i = head[now] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end])
getSize(Ed[i].end);
vis[now] = ;
} void getRoot(int now){
int maxN = ;
size[now] = vis[now] = ;
for(int i = head[now] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end]){
getRoot(Ed[i].end);
size[now] += size[Ed[i].end];
maxN = max(maxN , size[Ed[i].end]);
}
maxN = max(maxN , nowSize - size[now]);
if(maxN < minSize){
minSize = maxN;
minInd = now;
}
vis[now] = ;
} void getDis(int now , int fa , int cnt , int len){
be[now] = cnt;
dis[now] = len;
for(int i = head[now] ; i ; i = Ed[i].upEd)
if(Ed[i].end != fa)
getDis(Ed[i].end , now , cnt , len + Ed[i].w);
} void solve(int now){
nowSize = ;
minSize = 0x7fffffff;
getSize(now);
getRoot(now);
int root = minInd , cnt = , maxL = , allBe = ;
vis[root] = ;
dis[root] = be[root] = ;
for(int i = head[root] ; i ; i = Ed[i].upEd)
getDis(Ed[i].end , root , ++cnt , Ed[i].w);
for(int i = ; i <= M ; ++i)
maxL = max(maxL , dis[query[i][]] + dis[query[i][]]);
ans = min(ans , maxL);
for(int i = ; i <= M ; ++i)
if(dis[query[i][]] + dis[query[i][]] == maxL)
if(be[query[i][]] == be[query[i][]] && (!allBe || allBe == be[query[i][]]))
allBe = be[query[i][]];
else
if((!be[query[i][]] || !be[query[i][]]) && (!allBe || allBe == be[query[i][]] + query[i][]))
allBe = be[query[i][]] + be[query[i][]];
else
return;
for(int i = head[root] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end] && be[Ed[i].end] == allBe){
solve(Ed[i].end);
return;
}
} int main(){
N = read();
M = read();
ans = ;
for(int i = ; i < N ; ++i){
int a = read() , b = read() , c = read();
addEd(a , b , c);
addEd(b , a , c);
}
for(int i = ; i <= M ; ++i){
query[i][] = read();
query[i][] = read();
}
solve();
printf("%d" , ans);
return ;
}

Luogu4886 快递员 点分治的更多相关文章

  1. [luogu4886] 快递员(点分治,树链剖分,lca)

    dwq推的火题啊. 这题应该不算是点分治,但是用的点分治的思想. 每次找重心,算出每一对询问的答案找到答案最大值,考虑移动答案点,使得最大值减小. 由于这些点一定不能在u的两颗不同的子树里,否则你怎么 ...

  2. Noip前的大抱佛脚----赛前任务

    赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...

  3. 【洛谷 P4886】 快递员 (点分治)

    这题因为一些小细节还是\(debug\)了很久...不过我第一次用脚本对拍,不亏. 先随便找一个点作为根,算出答案,即所有点对到这个点的距离和的最大值,并记录所有距离最大的点对.如果这个点在任意一个距 ...

  4. luogub P4886 快递员(点分治)

    记得是9月月赛题,当时做的时候觉得跟ZJOI2015幻想乡战略游戏那道题很像???,就写了,然后就写挂了... 我们发现假设当前点为根,我们算出\(m\)次询问中最远的\(a\)对点,如果这\(a\) ...

  5. 一篇自己都看不懂的点分治&点分树学习笔记

    淀粉质点分治可真是个好东西 Part A.点分治 众所周知,树上分治算法有$3$种:点分治.边分治.链分治(最后一个似乎就是树链剖分),它们名字的不同是由于分治方式的不同的.点分治,顾名思义,每一次选 ...

  6. 【题解】P4886快递员

    [题解]P4886 快递员 淀粉质好题!!!加深了我对点分治的理解.最近分治学了好多啊. 题目大意 给定你一颗有边权的树,再给你\(m\)和点对,请你在树上选出来一个点,使得所有点对到这个点的距离的最 ...

  7. [bzoj2152][聪聪和可可] (点分治+概率)

    Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...

  8. POJ 2965. The Pilots Brothers' refrigerator 枚举or爆搜or分治

    The Pilots Brothers' refrigerator Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22286 ...

  9. [poj1741][tree] (树/点分治)

    Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...

随机推荐

  1. Android学习笔记----Java中的字符串比较

    用习惯了C#.C++,在做字符串比较时想当然地使用如下语句: string str1 = "abcd", str2 = "abcd"; if(str1==str ...

  2. 安卓开发_关于WebView加载页面空白问题

    依据我自己的测试,发现有时候用APP打开网页的时候,有的网页加载成功之前需要很久,有的一下就出来了(比如百度) 当加载时间过长的情况下,这时候显示的是空白界面,其实不是代码问题,只是要打开的这个网页太 ...

  3. Android 动态渐变按钮

    先上个图 看着特别炫酷吧 其实就是自定义颜色两秒轮播动画 AnimationDrawable animationDrawable = (AnimationDrawable) button.getBac ...

  4. 洗礼灵魂,修炼python(38)--面向对象编程(8)—从算术运算符进一步认识魔法方法

    上一篇文章了解了魔法方法,相信你已经归魔法方法至少有个概念了,那么今天就进一步的认识魔法方法.说这个之前,大脑里先回忆一下算术操作符. 什么是算术操作符?忘记没有?忘记了的自己倒回去看我前面的博文或者 ...

  5. 实战:阿里巴巴 DevOps 转型后的运维平台建设

    导读:阿里巴巴DevOps转型之后,运维平台是如何建设的?阿里巴巴高级技术专家陈喻结合运维自身的理解,业务场景的分析和业界方法论的一些思考,得出来一些最佳实践分享给大家.   前言   “我是这个应用 ...

  6. Linux运维平台工具:pstree、ps、top、htop、free、vmstat、dstat、kill、killall

    1.pstree命令 查看进程树,centos7下统一由systemd进行管理 [root@ELK-chaofeng systemd]# pstree systemd─┬─AliYunDun───*[ ...

  7. 联想笔记本Y7000P安装nvidia,cuda,tensorflow,pytorch

    Y7000P电脑环境i7处理器,1060显卡,16g内存,win10家庭版(系统版本号1809),在联想官网升级过bios,所有驱动都是最新.(截止时间点2019年3月1日) python3.5 安装 ...

  8. Django之views

    一 URL补充 二 Views试图函数 一 URL补充 1 MTV模型 2  django建立流程(用命令版) (1)django-admin startproject projectname (2) ...

  9. 合并多个Excel文件

    这条分享来自百度经验https://jingyan.baidu.com/article/e6c8503cb6ed7ee54e1a1811.html

  10. 阿里巴巴Web前端面试的一道JS题目,求解答!!!

    题目大概是这种: function outer(){ return inner; var inner = "a"; function inner(){}; inner = 9; } ...