前言

>原题传送门(洛谷)<

看了一下洛谷题面,这道NOI的题竟然是蓝的(恶评?),做了一下好像确实是蓝的...

解法

思路非常简单,找道树的直径,然后答案是直径长度加上最大的min(dis[pos1], dis[pos2]),pos1和pos2是指定的任意一条直径的两个端点,dis是距离

证明

鉴于这是一棵树(原题面:可以保证,任两个居住点间有且仅有一条通路。)

因此,我们最大的方案必然包含一条直径

可以稍加思考,如果不是直径的话一定能找到一种取直径的方法比它更大...

那么再任意找另一个点,因为要满足"如果A距离C比B距离C近走A,否则走B",所以任意一个点的贡献为min(dis[pos1], dis[pos2])。

题目要求最大的,所以取最大的min(dis[pos1], dis[pos2])

代码

树的直径显然只需要一个DFS,求解也只需要一个DFS,所以共计两个DFS

#include <cstdio>
#include <algorithm>
#define ll long long using namespace std; ll read(){
ll x = 0; int zf = 1; char ch = ' ';
while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if (ch == '-') zf = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
} struct Edge{
int to, next;
ll dis;
} edges[400005]; int head[200005], edge_num; void addEdge(int u, int v, ll w){
edges[++edge_num] = {v, head[u], w};
head[u] = edge_num;
} ll dis[200005];
ll dis2[200005][2]; void getDis(int u, int fa, ll vl){
int v; dis[u] = ((u == fa) ? 0 : dis[fa] + vl);
for (int c_e = head[u]; c_e; c_e = edges[c_e].next){
v = edges[c_e].to; if (v == fa) continue;
getDis(v, u, edges[c_e].dis);
}
} void getDis2(int u, int fa, ll vl, int op){
int v; dis2[u][op] = ((u == fa) ? 0 : dis2[fa][op] + vl);
for (int c_e = head[u]; c_e; c_e = edges[c_e].next){
v = edges[c_e].to; if (v == fa) continue;
getDis2(v, u, edges[c_e].dis, op);
}
} int main(){
int n = read(), m = read();
for (int i = 1; i <= m; ++i){
int u = read(), v = read(); ll w = read();
addEdge(u, v, w), addEdge(v, u, w);
}
getDis(1, 1, 0);
int pos1; ll _max = -1;
for (int i = 1; i <= n; ++i)
if (dis[i] > _max)
_max = dis[i], pos1 = i;
getDis(pos1, pos1, 0);
int pos2; _max = -1;
for (int i = 1; i <= n; ++i)
if (dis[i] > _max)
_max = dis[i], pos2 = i;
getDis2(pos1, pos1, 0, 0);
getDis2(pos2, pos2, 0, 1);
ll _max2 = -1;
for (int i = 1; i <= n; ++i)
_max2 = max(_max2, ((dis2[i][0] > dis2[i][1]) ? dis2[i][1] : dis2[i][0]));
printf("%lld", _max + _max2);
return 0;
}

备注

求树的直径:从任意一点开始DFS,找到最远点pos1,再从pos1开始DFS找到最远点pos2,

pos1和pos2即为树的直径

证明略(易证)

[NOI2003]逃学的小孩 题解的更多相关文章

  1. BZOJ1509 & 洛谷4408:[NOI2003]逃学的小孩——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=1509 https://www.luogu.org/problemnew/show/P4408 sb ...

  2. 洛谷 P4408 [NOI2003] 逃学的小孩 题解

    Analysis 题意虽然说先去谁家再去谁家,但是我们不需要管这个,因为AA.BB.CC三个点我们可以任意互相交换它们所代表的对象,所以题目要求的就是在一棵树上找到3个点AA.BB.CC令AB+BCA ...

  3. 【BZOJ1509】[NOI2003]逃学的小孩 直径

    [BZOJ1509][NOI2003]逃学的小孩 Description Input 第一行是两个整数N(3  N  200000)和M,分别表示居住点总数和街道总数.以下M行,每行给出一条街道的 ...

  4. [NOI2003]逃学的小孩(树的直径)

    [NOI2003]逃学的小孩 题目描述 Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:"喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?"一听 ...

  5. BZOJ 1509: [NOI2003]逃学的小孩( 树形dp )

    树形dp求出某个点的最长3条链a,b,c(a>=b>=c), 然后以这个点为交点的最优解一定是a+2b+c.好像还有一种做法是求出树的直径然后乱搞... ----------------- ...

  6. NOI2003 逃学的小孩

    这一题不会做啊…… 我觉得真要比赛的话我可能会随机上几万次,然后再用LCA求距离,更新最优值,等到快超时的时候输出答案…… 题解请看2007年陈瑜希论文 代码: ; type node=record ...

  7. BZOJ1509: [NOI2003]逃学的小孩 (树形DP)

    题意:给一棵树 选三个点A,B,C 求A到B的再从B到C的距离最大值 需要满足AB的距离小于AC的距离 题解:首先树上的最大距离就想到了直径 但是被样例误导了TAT BC两点构成了直径 我一开始以为A ...

  8. [NOI2003]逃学的小孩【观察+树的直径】

    Online Judge:Bzoj1509,Luogu P4408 Label:观察,树的直径 题目描述 输入 第一行是两个整数N(\(3≤N≤200000\))和M,分别表示居住点总数和街道总数.以 ...

  9. P4408 逃学的小孩 题解

    题目描述 Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:"喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?"一听说要考试,Chris的父母就心 ...

随机推荐

  1. jmeter链接数据库操作

    jmeter链接数据库操作步骤 首先要先下载mysql-connector-java-5.1.39-bin.jar驱动包 链接:https://pan.baidu.com/s/14F4rp4uH1hX ...

  2. 【MM系列】SAP OX09中的地址如何取

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP OX09中的地址如何取   ...

  3. 递归算法之排列组合-求一个集合S的m个元素的组合和所有可能的组合情况

    求一个集合S的m个元素组合的所有情况,并打印出来,非常适合采用递归的思路进行求解.因为集合的公式,本身就是递归推导的: C(n,m) = C(n-1,m-1) + C(n-1,m). 根据该公式,每次 ...

  4. python每日一练:0000题

    **第 0000 题:**将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种提示效果. 类似于图中效果 示例代码: from PIL import Image,Imag ...

  5. Double类型的数值 在写入excel时 如何去掉 科学计算法的 后面数值+ E的 情况

    Double start = 20190724100000.000; 写入excel时 是 201907E+13 但想要输出的是 20190724100000 这种格式 Java在java.math包 ...

  6. express 实现我猜你喜欢功能

    工具:利用cookie-parser中间件; 原理: 每次访问某一具体的文章,就表明可能客户端对这类文章感兴趣, 将这类文章的标签添加到cookie里,字段是like; 然后退回到含有 我猜你喜欢模块 ...

  7. mysql数据库问题———登录进去无法操作显示You must reset your password using ALTER USER statement before executing this statement

    linux操作mysql数据库,可以登陆进去,但是操作所有命令都显示You must reset your password using ALTER USER statement before exe ...

  8. Let's encrypt 通配域名DNS验证方式的证书自动更新

    通配符域名不同于一般的单域名证书. 为了解决之前一篇短文中通配域名通过DNS方式验证的证书自动更新问题. 需要使用到第三方域名提供商的API, 用于自动添加域名的TXT记录, 实现自动验证并完成证书更 ...

  9. 数据分析画图,使用原生sql查询数据

    1.使用工具 https://www.hcharts.cn/ http://echarts.baidu.com/ 2.子表查询 id 创建时间 内容 处理者 1 2017-02-01 11:11 1 ...

  10. Android数据库使用指南(下)

    前言 上面已经说了,对表进行修改,其实就是对数据库进行升级,删除表也算升级啊,反正就是发生变化,数据库就需要升级. 所以老实说其实有个地方决定了数据库的版本 public class DBHelper ...