Luogu4886 快递员 点分治
淀粉质好题啊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 快递员 点分治的更多相关文章
- [luogu4886] 快递员(点分治,树链剖分,lca)
dwq推的火题啊. 这题应该不算是点分治,但是用的点分治的思想. 每次找重心,算出每一对询问的答案找到答案最大值,考虑移动答案点,使得最大值减小. 由于这些点一定不能在u的两颗不同的子树里,否则你怎么 ...
- Noip前的大抱佛脚----赛前任务
赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...
- 【洛谷 P4886】 快递员 (点分治)
这题因为一些小细节还是\(debug\)了很久...不过我第一次用脚本对拍,不亏. 先随便找一个点作为根,算出答案,即所有点对到这个点的距离和的最大值,并记录所有距离最大的点对.如果这个点在任意一个距 ...
- luogub P4886 快递员(点分治)
记得是9月月赛题,当时做的时候觉得跟ZJOI2015幻想乡战略游戏那道题很像???,就写了,然后就写挂了... 我们发现假设当前点为根,我们算出\(m\)次询问中最远的\(a\)对点,如果这\(a\) ...
- 一篇自己都看不懂的点分治&点分树学习笔记
淀粉质点分治可真是个好东西 Part A.点分治 众所周知,树上分治算法有$3$种:点分治.边分治.链分治(最后一个似乎就是树链剖分),它们名字的不同是由于分治方式的不同的.点分治,顾名思义,每一次选 ...
- 【题解】P4886快递员
[题解]P4886 快递员 淀粉质好题!!!加深了我对点分治的理解.最近分治学了好多啊. 题目大意 给定你一颗有边权的树,再给你\(m\)和点对,请你在树上选出来一个点,使得所有点对到这个点的距离的最 ...
- [bzoj2152][聪聪和可可] (点分治+概率)
Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...
- POJ 2965. The Pilots Brothers' refrigerator 枚举or爆搜or分治
The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22286 ...
- [poj1741][tree] (树/点分治)
Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...
随机推荐
- vue-cli脚手架之webpack.base.conf.js
webpack相关的重要配置文件将在这一节给出.webpack水很深啊^o^,在此先弄清楚原配文件内容的含义,后续可以自己根据实际情况配置. webpack.base.conf.js:配置vue开发环 ...
- App里面如何正确显示用户头像
1.说明,一般用户头像在上传的时候都会处理为正方形,如果没有处理该怎么正确显示用户头像呢?解决方案:用css强制 在线地址移动端:戳这里 <div class="main-meimg& ...
- 伪类选择器 E:nth-child(n)、E:nth-of-type(n)
结构伪类是css3新增的类型选择器. E:nth-child(n).E:nth-of-type(n)就是其中之二.搞懂了这两个,基本上跟他俩一家的其他几个兄弟伙基本上也可以弄懂了. 首先先用文字语言来 ...
- Leaflet 测试加载高德地图
<!DOCTYPE html> <html> <head> <title>Leaflet Quick Start Guide Example</ ...
- loadrunner 场景设计-负载生成器管理
场景设计-负载生成器管理 by:授客 QQ:1033553122 1 简介 当执行一个场景时,Controller把场景中的每个用户配到负载生成器(Load generator). 所谓的负载生成器 ...
- Nodejs 安装 on centos7
本文演示如何在CentOS7上安装Nodejs. 1 准备工作 1.1 浏览器访问安装包下载地址: https://nodejs.org/dist/ 找到需要安装的版本,以8.11.3版本为例,地址为 ...
- MongoDB的安装与python操作MongoDB
一.安装MongoDB 因为我个人使用的是windows,就只记录下windows下的安装 1.下载安装 就是官网,下载msi,选个路径安装 2.配置 看见别的地方说需要手动在bin同级目录创建dat ...
- 代理ARP--善意的欺骗
1. 代理ARP(Proxy ARP)是什么? 顾名思义,它指通过中间设备(通常为Router)代替其他主机响应ARP请求.对于没有配置默认网关的主机想要与其他网络的另一台主机通信时,网关收到源主机的 ...
- 【PAT】B1060 爱丁顿数(25 分)
逻辑问题,对我来说还是挺有难度的,一开始想不通 我输入数据并以数据为下标,数据出现次数为内容存储 然后从后遍历计算所有大于当前下标的元素出现的次数 最后遍历一遍确定是否为爱丁顿数,如果大于当前已经找到 ...
- 17秋 软件工程 团队第五次作业 Alpha 用户反馈
用户反馈 Bug 测试对不同机型进行了测试,包括: 小米NOTE, MIUI 8.5 稳定版 [已修复]点登录按钮之后自动退出: [已修复]登录界面的背景图片没有显示. 小米4 [已修复]闪退,无法打 ...