[NOI2003]逃学的小孩 --- 树的直径_笑面蘑菇的博客-程序员宅基地

技术标签: 树的直径  

传送门:洛谷P4408


题目描述

Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:“喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?”一听说要考试,Chris的父母就心急如焚,他们决定在尽量短的时间内找到Chris。他们告诉Chris的老师:“根据以往的经验,Chris现在必然躲在朋友Shermie或Yashiro家里偷玩《拳皇》游戏。现在,我们就从家出发去找Chris,一但找到,我们立刻给您打电话。”说完砰的一声把电话挂了。

Chris居住的城市由N个居住点和若干条连接居住点的双向街道组成,经过街道x需花费Tx分钟。可以保证,任两个居住点间有且仅有一条通路。Chris家在点CShermie和Yashiro分别住在点A和点B。Chris的老师和Chris的父母都有城市地图,但Chris的父母知道点A、B、C的具体位置而Chris的老师不知。

为了尽快找到Chris,Chris的父母会遵守以下两条规则:

  1. 如果A距离C比B距离C近,那么Chris的父母先去Shermie家寻找Chris,如果找不到,Chris的父母再去Yashiro家;反之亦然。
  2. Chris的父母总沿着两点间唯一的通路行走。

显然,Chris的老师知道Chris的父母在寻找Chris的过程中会遵守以上两条规则,但由于他并不知道A,B,C的具体位置,所以现在他希望你告诉他,最坏情况下Chris的父母要耗费多长时间才能找到Chris?


分析

树的直径题都这么毒瘤么,题面不可读系列
可以将题目的要求拆成两部分 求 A → B / C A\to B / C AB/C 最小值的最大值 和 B → C B \to C BC的最大值
求树上最长路径的的话,那就是树的直径了, 因此 B → C B \to C BC必定为树的直径.两遍dfs确定好 B B B C C C点即可,
对于 A → B / C A\to B / C AB/C,可以将其拆成两部分, A → P A \to P AP(P在树的直径上),以及 m i n ( P → B , P → C ) min(P \to B, P \to C) min(PB,PC),对此,枚举直径上的每个点,求出不经过直径其他点最长距离(即为 A → P A \to P AP).比较更新答案即可.


代码

#include <cstdio>
#include <cstdlib>
#include <cstring>

#define IL inline

using namespace std;

IL int read()
{
     
    char c = getchar();
    int sum = 0 ,k = 1;
    for(;'0' > c || c > '9'; c = getchar())
        if(c == '-') k = -1;
    for(;'0' <= c && c <= '9'; c = getchar()) sum = sum * 10 + c - '0';
    return sum * k;
}

int to[400005], nxt[400005], val[400005];
int last[200005];
int cnt;
IL void add(int u, int v, int w)
{
     
    to[++cnt] = v; nxt[cnt] = last[u]; val[cnt] = w; last[u] = cnt;
    to[++cnt] = u; nxt[cnt] = last[v]; val[cnt] = w; last[v] = cnt;
}

typedef long long ll;

int n, m;
ll dis[200005];
int fa[200005];

bool check[200005];
IL ll min_(ll x, ll y) {
      return x < y ? x : y; }
IL ll max_(ll x, ll y) {
      return x > y ? x : y; }

IL void dfs(int u, int &p)
{
     
    if(dis[u] > dis[p]) p = u;
    for(int i = last[u], v; (v = to[i]); i = nxt[i])
    if(v != fa[u])
    {
     
        dis[v] = dis[u] + val[i];
        fa[v] = u;
        dfs(v, p);
    }
}

IL void dfs2(int u, int pre, ll d, ll &maxd)
{
     
    if(d > maxd) maxd = d;
    for(int i = last[u], v; (v = to[i]); i = nxt[i])
    if(v != pre && !check[v])
        dfs2(v, u, d + val[i], maxd);
}

int main()
{
     
    n = read(); m = read();
    
    for(int i = 1, x, y; i <= m; ++i)
    {
     
    	x = read(); y = read();
    	add(x, y, read());
    }
    
    int S = 0, T = 0;
    dfs(1, T);
    dis[T] = 0; fa[T] = 0;
    dfs(T, S);
    
    for(int i = S; i; i = fa[i])
    	check[i] = 1;
    ll ans = 0, maxd;
    for(int i = S; i; i = fa[i])
    {
     
    	maxd = 0;
    	dfs2(i, 0, min_(dis[i], dis[S] - dis[i]), maxd);
    	ans = max_(ans, maxd);
    }
    ans += dis[S];
    printf("%lld\n", ans);
    
    return 0;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_27121257/article/details/82011008

智能推荐

arm-linux-cc 4.4.3 交叉编译gstreamer1.18_no tls backends enabled_倾我一生来读的博客-程序员宅基地

1 下载glib失败gstreamer 依赖glib,所以编译的时候检测到toolchain中没有安装glib的话会自动从git仓库拉取代码,但是国内访问github或者gitlib比较慢,会出现time out的问题。fatal: unable to access 'https://gitlab.gnome.org/GNOME/glib.git/': Failed to connect to gitlab.gnome.org port 443: Connection timed outsubproj

【测试文档】软件测试工程师:岗位描述文案_软件测试工程师的职位介绍怎么写_顾三殇的博客-程序员宅基地

目录一、初级软件测试工程师二、中级软件测试工程师三、高级软件测试工程师一、初级软件测试工程师(1)年限:1 ~ 3 年/ 1 年以内 / 应届生 / 实习生(2)学历:大专及以上(3)岗位职责:1、根据需求和交付要求编写测试用例;2、有效地执行测试用例;3、能基本定位并跟踪缺陷,推动缺陷及时合理地解决;4、能完成对产品的功能、接口测试;5、具有良好的理解分析能力、判断能力、写作能力、沟通表达能力、执行能力;6、定期向上级报告工作,提交工作日报周报,完成上级交付的各

Elasticsearch核心术语与安装、head与postman基于索引的基本操作_@所谓伊人的博客-程序员宅基地

一、Elasticsearch核心术语1.核心概念ES -&gt; 数据库索引index -&gt; 表文档 document -&gt; 行(记录)字段 fields -&gt; 列文档以json的形式存在:stu_index{id: 1001,name: jason,age: 19},{id: 1002,name: tom,age: 18},{id: 1003,name: rose,age: 22}2.集群相关分片(shard):把索引

Protege 5.5 的OWLViz堆叠一块无法正常显示,通过下载设置GraphViz解决_protege5.5.0 owlviz在哪_集电极的博客-程序员宅基地

Protege 5.5 的OWLViz堆叠一块无法正常显示,通过下载设置GraphViz解决文章目录Protege 5.5 的OWLViz堆叠一块无法正常显示,通过下载设置GraphViz解决1.1GraphViz下载1.2GraphViz设置1.3效果1.1GraphViz下载下载地址:https://graphviz.org/download/step1step2step31.2GraphViz设置step1:把GraphViz压缩包解压到预定位置,推荐把解压包放在Prote

UnicodeDecodeError:utf-8 codec can't decode byte 0xc8 in position_rm_ing的博客-程序员宅基地

打代码的时候出现了这样的错误查了一下网上的方法 用Notepad++的将编码改成用utf-8 修改之后我依旧报错。然后也有人说是因为路径中出现了中文,但我实际上并没有。而windows系统是用GBK编码的,因此尝试将出现问题的那一句(也就是报错信息中我用红色标注的)'utf-8'改成‘gbk',问题解决。...

java解压zip格式文件和rar的格式_java解压zip文件_tiger_angel的博客-程序员宅基地

/** * 解压zip格式文件 * */ public static void Decompressing2() throws IOException { String Inputpath = &quot;E:/b&quot;;//压缩包地址 String outpath = &quot;E:/a&quot;;//解压到的文件地址 String FileName=&quot;&quot;;//文件名称 Zi...

随便推点

内核-内核移植_邻居家的小南瓜的博客-程序员宅基地

注:PRIMASK:1 bit寄存器。注:此汇编代码会设置 PendSV 异常优先级为最低优先级,并将MSP设置为SCB_VTOR(向量表放的第一个元素是sp)线程环境下,如果调用 rt_hw_context_switch() 函数,那么可以马上进行上下文切换;1)使用 MRS 指令将 PRIMASK 寄存器的值保存到 r0 寄存器里。而在中断环境下,需要等待中断处理函数完成之后才能进行切换。2)使用 “CPSID I” 指令关闭全局中断。NVIC_PENDSV_PRI:内核寄存器。

UKF-MATLAB-仿真_ukf算法c代码_江湖 路人的博客-程序员宅基地

代码来源转载来源 构建Sigma点的函数 [plain] view plain copy function&nbsp;X&nbsp;=&nbsp;sigmas(x,P,c)&nbsp;&nbsp;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&nbsp;&nbsp;%&nbsp;Sigma&nbsp;points&

【Socket.io 提示 Invalid frame header】-程序员宅基地

后来,还是把服务端 socket.io 的版本改了回来,去官网找到对应版本的客户端 socket.io 下载替换。最近在网上疯狂地找与聊天系统有关的资源,因为之前没做过,好长时间找到一个看起来比较容易的,准备跑起来。然后我把 package.json 改成大佬使用的版本,重新下载依赖运行成功了…于是我把大佬的代码内容放到我的服务器下边,好,运行。我的服务端 socket.io 的版本是 4.5.2。客户端输入大佬的地址,好,信息接受成功。说的是,服务端与客户端的兼容性问题。然后大佬的代码跑起来了。

C++ substr实现截取字符串_c++ substring截取字符串_大数据秃头族的博客-程序员宅基地

s.substr(n,length)//表示从字符串n的位置开始截取length长度的字符。字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。s.substr(n)//表示从字符串n的位置开始截取到最后。和数字 22,该函数将返回左旋转 22 位得到的结果。输入字符串长度 [0,1000][0,1000]。请定义一个函数实现字符串左旋转操作的功能。

在Linux与Windows环境下安装MySQL_mysqlwindow还是linux_CodeDevMaster的博客-程序员宅基地

记录在Linux环境与Windows环境下安装MySQL的详细过程,以及使用Docker安装MySQL

推荐文章

热门文章

相关标签