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.test.conf.js
webpack单元测试配置: // This is the webpack config used for unit tests. var utils = require('./utils')//ut ...
- jQuery中bind() live() delegate() on() 的区别
实例 bind(type,[data],fn) 为每个匹配元素的特定事件绑定事件处理函数 $("a").bind("click",function(){aler ...
- [VUE ERROR] Error in render: "TypeError: Cannot create property 'header' on boolean 'true'"
项目基于ElemnetUi进行的开发,在引入第三方扩展库 vue-element-extends 之后使用它的表格组件报了这个错 解决方案: 1. 删除项目中的 node_modules 2. 删除 ...
- 交叉编译器 arm-linux-gnueabi 和 arm-linux-gnueabihf 的区别
交叉编译器 arm-linux-gnueabi 和 arm-linux-gnueabihf 的区别 自己之前一直没搞清楚这两个交叉编译器到底有什么问题,特意google一番,总结如下,希望能帮到道上和 ...
- loadrunner 脚本开发-参数化之将内容保存为参数、参数数组及参数值获取Part 2
脚本开发-参数化之将内容保存为参数.参数数组及参数值获取 by:授客 QQ:1033553122 ----------------接 Part 1--------------- 把内容保存到参数数组 ...
- 浅谈Java多线程中的join方法
先上代码 新建一个Thread,代码如下: package com.thread.test; public class MyThread extends Thread { private String ...
- Android系统启动流程 总结
整体流程大致如下: Android系统的启动,主要是指Android手机关机后,长按电源键后,Android手机开机的过程.从系统角度看,Android的启动程序可分为: 1.bootload ...
- CSS网页菜单
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserContro ...
- 关于elk中filebeat定义好日志输出,但是redis里面却没有输出内容的问题
这两天在搞elk的时候,filebeat中指定输出日志至Broker(此处Broker采用redis作为缓存),但是redis中却没有内容,所以就开始排查来 filebeat采用RPM安装的方式来的. ...
- February 2nd, 2018 Week 5th Friday
Reputation takes a life time to build and a second to destroy. 树立名声需要一生的努力,而毁掉它只需要一秒. To be a smart ...