Luogu_4886 快递员
一道淀粉质的题目。
先考虑最简单的算法,那便是对每个点都求一边。时间复杂度O(NM)
然后如果我们把每个点的结果对应一个高度,我们会发现。最优解是在这个对应高度形成的三维图像中的谷底(谷缝)
也就数说,对于一条链来说,他是一个开口向上的类似二次函数的一个图形。
具有类似单调性的一类性质。
在O(NM)的算法中,可以使用其剪枝。既是如果相邻的节点的答案要大于当前节点,那么我们就不向那个节点进行搜索。
为什么? 如果相邻节点的答案小于当前点,那么说明,当前的最长链的两端都在相邻节点所确定的子树中。
所以我们往这颗子树中走就用可能是更优的。(随时取min)
为什么说是可能?因为这个最长链的位置可能改动。
对于这个二次函数图像,我们可以使用一个类似二分的方法,在log时间复杂度中找到最小值。
就是前文说的类似单调性一样的东西。
所以我们可以利用最长连所在的子树的重心进行检验。
因为重心的性质,我们就可以每次将问题至少缩小一半规模。
至于什么时候退出呢?
要么递归到底,要么子树重心的答案大于当前最优答案。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using std::min;
using std::max;
const int maxn=101000;
const int inf=0x7fffffff;
struct node
{
int p;
int value;
int nxt;
};
node line[maxn<<1];
int head[maxn],tail;
int query[maxn][2];
int vis[maxn],dis[maxn],size[maxn],f[maxn];
int belong[maxn];
int n,m,root,sum;
int ans,where;
int read()
{
char c=getchar();
int res=0;
while(c>'9'||c<'0') c=getchar();
while(c>='0'&&c<='9')
{
res=(res<<1)+(res<<3)+c-'0';
c=getchar();
}
return res;
}
void add(int a,int b,int c)
{
line[++tail].p=b;
line[tail].value=c;
line[tail].nxt=head[a];
head[a]=tail;
return ;
}
void get_dis(int now,int fa,int Dis,int Belong)
{
dis[now]=Dis;
belong[now]=Belong;
for(int i=head[now];i;i=line[i].nxt)
{
int v=line[i].p;
if(v==fa) continue;
get_dis(v,now,Dis+line[i].value,Belong);
}
return ;
}
void get_size(int now,int fa)
{
size[now]=1;
for(int i=head[now];i;i=line[i].nxt)
{
int v=line[i].p;
if(vis[v]||v==fa) continue;
get_size(v,now);
size[now]+=size[v];
}
return ;
}
void get_hry(int now,int fa)
{
size[now]=1;f[now]=0;
for(int i=head[now];i;i=line[i].nxt)
{
int v=line[i].p;
if(vis[v]||v==fa) continue;
get_hry(v,now);
size[now]+=size[v];
f[now]=max(f[now],size[v]);
}
f[now]=max(f[now],sum-size[now]);
if(f[now]<f[root]) root=now;
return ;
}
void solve(int now)
{
sum=size[now];
root=0;
get_hry(now,0);
int Max=0,Be=0,cnt=0;
vis[root]=1;get_size(root,0);
belong[root]=dis[root]=0;
for(int i=head[root];i;i=line[i].nxt)
get_dis(line[i].p,root,line[i].value,++cnt);
for(int i=1;i<=m;i++)
Max=max(Max,dis[query[i][0]]+dis[query[i][1]]);
ans=min(ans,Max);
// if(ans>Max)
// {
// ans=Max;
// where=root;
// }
for(int i=1;i<=m;i++)
{
int A=query[i][0],B=query[i][1];
if(dis[A]+dis[B]!=Max) continue;
if(belong[A]==belong[B]&&(!Be||Be==belong[A]))
Be=belong[A];
else if((!belong[A]||!belong[B])&&(!Be||Be==belong[A]+belong[B]))
Be=belong[A]+belong[B];
else return ;
}
for(int i=head[root];i;i=line[i].nxt)
if(!vis[line[i].p]&&Be==belong[line[i].p])
{
solve(line[i].p);
return ;
}
return ;
}
int main()
{
n=read();m=read();
for(int i=1,a,b,c;i<n;i++)
{
a=read();b=read();c=read();
add(a,b,c);
add(b,a,c);
}
for(int i=1;i<=m;i++)
query[i][0]=read(),query[i][1]=read();
f[0]=inf;size[1]=n;ans=inf;
solve(1);
printf("%d",ans);
//printf("\n%d",where);
}
Luogu_4886 快递员的更多相关文章
- easyUI定区关联快递员js代码
easyUI定区关联快递员js代码: <script type="text/javascript"> $.fn.serializeJson=function(){ va ...
- Android动画之仿美团加载数据等待时,小人奔跑进度动画对话框(附顺丰快递员奔跑效果)
Android动画之仿美团加载数据等待时,小人奔跑进度动画对话框(附顺丰快递员奔跑效果) 首句依然是那句老话,你懂得! finddreams :(http://blog.csdn.net/finddr ...
- 项目一:第七天 CRM 和bos系统实现定区关联客户,关联快递员. 通过CXF框架实现
定区关联客户 需求:为了快递方便客户下订单(发快递),派快递员上门取件. 所以说需要让定区关联客户(知道客户属于哪个定区),定区跟快递员关系:多对多.知道让哪个快递员上门取件. 将CRM系统中,客户 ...
- 项目一:第四天 1、快递员的条件分页查询-noSession,条件查询 2、快递员删除(逻辑删除) 3、基于Apache POI实现批量导入区域数据 a)Jquery OCUpload上传文件插件使用 b)Apache POI读取excel文件数据
1. 快递员的条件分页查询-noSession,条件查询 2. 快递员删除(逻辑删除) 3. 基于Apache POI实现批量导入区域数据 a) Jquery OCUpload上传文件插件使用 b) ...
- 项目一:第三天 收派标准添加 收派标准分页查询(基于datagrid实现) 收派标准修改快递员添加 快递员列表查询
1.收派标准添加 n jQuery easyUI window使用 n jQuery easyUI form表单校验 n 收派标准添加页面调整—url params n 服务端实现—三层 2.jQue ...
- 【题解】P4886快递员
[题解]P4886 快递员 淀粉质好题!!!加深了我对点分治的理解.最近分治学了好多啊. 题目大意 给定你一颗有边权的树,再给你\(m\)和点对,请你在树上选出来一个点,使得所有点对到这个点的距离的最 ...
- [P4886] 快递员
考虑在树上选个点rt作为根,并且快递中心就选这儿.计算出所有配送的代价(2*两段之和),设他们的最大值为Max.若此时存在下列情况时,可以判定Max已经为最优解. 1)存在代价为Max的配送(u,v) ...
- Luogu4886 快递员 点分治
传送门 淀粉质好题啊qaq 我们先考虑随便选择一个点作为邮递中心,通过移动邮递中心找到更优的位置.将路径最大值求出,并将路径最大值对应的那一些路径拿出来考虑.可以知道,如果说这些路径中存在一条经过当前 ...
- 【LGP4886 】快递员
题目 好秒啊,真是一道神仙的点分治 于是我们来一个暴力的\(O(nlog^2n)\)的暴力统计吧 考虑计算每一个点作为快递中心时的答案 我们考虑在这个点成为分治重心时计算这个贡献 把这个贡献分成两部分 ...
随机推荐
- Hunger Snake3
- 【Chromium】sandboxed window问题记录
问题发现 在业务逻辑中发现有时使用chrome.app.window.create这个API创建出来的窗口无法使用其他的API,不仅其他chrome.app.window的API说window is ...
- python可变容器类型做函数参数的坑
def extendList(val, list=[]): # []默认参数的只指向一个地址 list.append(val) return list list1 = extendList(10) l ...
- Spring中的BeanFactory和ApplicationContext的区别
我用一个例子去测试BeanFactory和ApplicationContext的区别 首先建立一个bean public class User { //声明无参构造,打印一句话,监测对象创建时机 pu ...
- 51NOD1847:奇怪的数学题
传送门 Sol 设 \(f(d)\) 表示 \(d\) 所有约数中第二大的,\(low_d\) 表示 \(d\) 的最小质因子 \[f(d)=\frac{d}{low_d}\] 那么 \[\sum_{ ...
- Qt Quick程序的发布
要将程序发布出去,首先需要使用release方式编译程序,然后将生成的.exe可执行文件和需要的库文件发在一起打包进行发布. 要确定需要哪些动态库文件,可以直接双击.exe文件,提示缺少那个dll文件 ...
- selenium元素定位方法
一.如何找到页面元素 Webdriver的findElement方法可以用来找到页面的某个元素,最常用的方法是用id和name查找.下面介绍几种比较常用的方法. 1.1By ID 假设页面写成这样:i ...
- PRINCE2的优势有哪些?
PRINCE2之所以迅速发展的原因之一是许多企业认识到建立适合自己企业的项目管理标准是一项耗时耗财的工作. 他们至少要花费6-12个月.成千上万个工时来建立一套方法,而这只是最初的成本. 之后他们必须 ...
- Windows10禁用update
1.运行 gpedit.msc 或搜索 组策略 ,点 计算机配置—管理模板—Windows组件—Windows更新—配置自动更新 ,设置“已禁用”.2.点 控制面板—系统和安全—管理工具 ,点 服务 ...
- Python初学者第十七天 函数(1)
17day 函数 1.函数定义: 函数 是指将一组语句的集合通过一个名字(函数名)封装起来,想要执行这个函数,只需调用其函数名即可 2.函数的特性: a 减少重复代码 b 使程序变得可扩展 c 使程序 ...