[bzoj1999][noip2007]Core树网的核
好久没写题解了。这题不算太水就写一下题解。
话说回来,虽然不水但是挺裸。可以说题意即一半题解了。
我猜粘了题面也没有人去看的,所以直接人话题意了。
给一棵树,点数1e6,(当年noip的n当然是只有300了,,),就管他叫树网。
首先定义树的直径:树上最远点对之间的路径。我们定义树的一个点到一段路径的距离是:点和路径上最近的点之间路径长。
然后定义一段路径的偏心距ecc:除了这这路径上的点,其他点到这条路径的距离中的max。(和所有点没区别)
现在要求出这样一个路径,它在一条直径上(直径可能不止一个),它的长度不超过一个给定的值lim,满足前两个条件的情况下偏心距最小。我们叫他树网的核。(终于扣题了woc)
所以我们需要知道一些事情。
1,树的直径可能不止一个,但不论用哪个直径所能求出的该最小偏心距相等。
2,离一个点最远的点一定是一条直径的一端。
虽然我不知道为啥。。但我觉得很有道理啊对不对。。。
于是在这基础上思路就很明显。
先根据性质2求出一条直径。然后显然是不超过lim情况下这一段越长越好。于是枚举结束点,开始点随之后移(就是双指针啥的扫一遍)。
对于一条路径其偏心距有两种情况:
1,开始点或结束点与所在直径上离得近的那个端点的距离。
2,不经过所在直径的情况下,能到达的其他点中与它距离最远的距离。
仔细想想(YY)一下就知道,不理解,,,私吧。
情况2与起始点结束点无关,可以预处理f(x),复杂度是O(n)的,因为一个点只会被遍历一次。
于是情况2变成了单调队列问题:求区间最大值,,不是定长区间了,deque的pop_front条件变为了q.front()与当前枚举的结束点距离<lim。
要注意的是q.front()并不是起始点,而是起始点到结束点中f(x)最大的。(好像只有我这么想脑残wa了一发)起始点是贪心选的,因为越长越好,只要不超过lim就好。
貌似没有什么细节问题了,dfs还是巨好写的。附代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
const int N=;
inline int read(){
int r=,c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c))
r=r*+c-'',c=getchar();
return r;
}
struct Edge{
int to,nxt,w;
}e[N*];
int head[N],cnt=;
void add(int u,int v,int w){
e[cnt]=(Edge){v,head[u],w};
head[u]=cnt++;
e[cnt]=(Edge){u,head[v],w};
head[v]=cnt++;
}
int n,lim,mx;
int S,T,d[N];
bool ind[N];
void dfs(int u,int fa){
mx=max(mx,d[u]);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa||ind[v])continue;
d[v]=d[u]+e[i].w;
dfs(v,u);
}
}
int nxt[N],dis[N];
void dfs2(int u,int fa){
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa)continue;
dfs2(v,u);
if(ind[v])
nxt[u]=v,dis[u]=e[i].w,ind[u]=;
}
}
void init(){
n=read(),lim=read();
for(int i=;i<n;i++){
int u=read(),v=read(),w=read();
add(u,v,w);
}
}
void diameter(){
mx=;dfs(,);
for(int i=;i<=n;i++)
if(d[i]==mx)S=i;
memset(d,,sizeof d);
mx=;dfs(S,);
for(int i=;i<=n;i++)
if(d[i]==mx)T=i;
}
int l[N],f[N];
void get(){
ind[T]=;dfs2(S,);
int t=;
for(int u=S;u;u=nxt[u]){
d[u]=mx=;l[u]=t;
t+=dis[u];
dfs(u,);f[u]=mx;
}
}
void solve(){
deque<int>q;
q.push_back(S);
int ans=2e9,h=S;
for(int u=S;u;u=nxt[u]){
int m=f[u];
while(!q.empty()&&f[q.back()]<m)
q.pop_back();
q.push_back(u);
while(l[u]-l[q.front()]>lim)
q.pop_front();
int v=q.front();
while(l[u]-l[h]>lim)h=nxt[h];
ans=min(ans,max(f[v],max(l[h],l[T]-l[u])));
}
printf("%d\n",ans);
}
int main(){
init();
diameter();
get();
solve();
}
欢迎dalaoD我,鄙视dalao装弱%我。。。
[bzoj1999][noip2007]Core树网的核的更多相关文章
- [BZOJ1999][codevs1167][Noip2007]Core树网的核
[BZOJ1999][codevs1167][Noip2007]Core树网的核 试题描述 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T为树网(t ...
- BZOJ_1999_[Noip2007]Core树网的核_单调队列+树形DP
BZOJ_1999_[Noip2007]Core树网的核_单调队列+树形DP Description 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T ...
- 【bzoj1999】[Noip2007]Core树网的核 树的直径+双指针法+单调队列
题目描述 给出一棵树,定义一个点到一条路径的距离为这个点到这条路径上所有点的距离的最小值.求一条长度不超过s的路径,使得所有点到这条路径的距离的最大值最小. 输入 包含n行: 第1行,两个正整数n和s ...
- 洛谷 1099 ( bzoj 1999 ) [Noip2007]Core树网的核
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1999 <算法竞赛进阶指南>346页.https://www.cnblogs.co ...
- [Noip2007]Core树网的核
嘟嘟嘟 首先求树的直径两次bfs即可,实际上bfs就是最短路,因为树上路径是唯一的,所以用任何一种遍历方法都行(spfa和dijkstra当然也可以). 可以证明,只要求出任意一条直径就行了,为什么呢 ...
- bzoj 1999: [Noip2007]Core树网的核【树的直径+单调队列】
我要懒死了,所以依然是lyd的课件截图 注意是min{max(max(d[uk]),dis(u1,ui),dis(uj,un))},每次都从这三个的max里取min #include<iostr ...
- 【BZOJ1999】【NOIP2007】树网的核 单调队列优化DP
题目描述 题目很长,大家自己去看吧. bzoj vijos 原题\(n\leq 300\) 加强版\(n\leq 500000\) 题解 这种东西当然要猜结论的啦,否则会比较麻烦. 结论1:如果有很多 ...
- 【noip2007】树网的核
题解: 首先我们要知道一个性质:如果有多条直径 这个核不论在哪条直径上 答案都是一样的 这样我们就可以随便找一条直径 在这条直径上枚举核的位置 并且dfs预处理maxlon[i] (i在直径上) 表示 ...
- 【DFS好题】BZOJ1999- [Noip2007]Core树网的核(数据加强版)
NOIP的数据好水,一开始有好几个错结果NOIP数据就水过了?? [题目大意] 求无根树的直径上一段不超过S长的链,使得偏心距最小.具体概念见原题. [思路] 首先明确几个性质: (1)对于树中的任意 ...
随机推荐
- APP常用检测
检测设备.微信平台和app是否安装 // 检测是否安装了APP var isappinstalled = (function () { ); }()), // 检测ios设备 isIOS = (fun ...
- u-boot分析(十)----堆栈设置|代码拷贝|完成BL1阶段
u-boot分析(十) 上篇博文我们按照210的启动流程,分析到了初始化nand flash,由于接下来的关闭ABB比较简单所以跳过,所以我们今天按照u-boot的启动流程继续进行分析. 今天我们会用 ...
- Qt开发北斗定位系统融合百度地图API及Qt程序打包发布
Qt开发北斗定位系统融合百度地图API及Qt程序打包发布 1.上位机介绍 最近有个接了一个小型项目,内容很简单,就是解析北斗GPS的串口数据然后输出经纬度,但接过来觉得太简单,就发挥了主观能动性,增加 ...
- Spring Cloud入门程序——注册服务提供者
1.创建Spring Starter project 2.引入依赖 点击finish 3.创建启动类 package com.hello; import org.springframework.boo ...
- Anaconda上安装Tensorflow并在jupyter上运行
博客原文地址:https://blog.csdn.net/index20001/article/details/73555182 https://www.cnblogs.com/HongjianChe ...
- 笨办法学Python(二十)
习题 20: 函数和文件 回忆一下函数的要点,然后一边做这节练习,一边注意一下函数和文件是如何在一起协作发挥作用的. from sys import argv script, input_file = ...
- 6.Netbackup-Oracle数据库恢复演练报告(下)
1.1 Oracle数据库恢复 目录 1 安装新的客户端 2 新建异机恢复文件 3 新建数据库实例 4 建立spfile文件 5 建立数据文件夹 6 启动数据库到nomount状态 7 列出备份信息 ...
- php简单开启gzip压缩方法(zlib.output_compression)
网上的教程基本是你抄我来我抄他,不外乎加头加尾或者自构函数两种写法.实际上每个php页面都要去加代码——当然也可以include引用,不过总显得略微麻烦 一般而言,页面文件开启gzip压缩以后,其 ...
- 2017.11.23 利用Cookie管理实现自动登陆
Cookie管理 Cookie对象是由服务器产生并保存在客户端的信息,常用他记录用户个人信息以及个性化设置.用户每次访问网点时,应用程序就可以检索以前保存的信息 Cookie对象属于的类是javax. ...
- 继续折腾LNK 2005错误
这次是因为要把一个很久的老项目改成使用Unicode字符集,又一次遇到了LNK 2005错误 先说说怎么把老项目改成Unicode字符集吧,首先要有足够的信心能把项目改好,比如我这次改的项目,也不算很 ...