Online JudgeBzoj1509Luogu P4408

Label:观察,树的直径

题目描述

输入

第一行是两个整数N(\(3≤N≤200000\))和M,分别表示居住点总数和街道总数。以下M行,每行给出一条街道的信息。第i+1行包含整数Ui、Vi、Ti(\(1≤Ui, Vi ≤ N,1≤Ti≤1000000000\)),表示街道i连接居住点Ui和Vi,并且经过街道i需花费Ti分钟。街道信息不会重复给出。

输出

仅包含整数T,即最坏情况下Chris的父母需要花费T分钟才能找到Chris。

样例

Input

4 3
1 2 1
2 3 1
3 4 1

Output

4

题解

【大致题意】

在树上选三个点,设家在A,现在要去B,然后再从B到C。请你求出最大的总路程\(AB+BC\),且满足\(AB<AC\)。

假设现在已经确定了路径\(BC\),该如何去找最优的\(A\)?预处理两个数组\(g[i][0/1]\)分别表示点i到端点\(B/C\)的距离,则有\(ans=dis(BC)+max(min(g[i][0],g[i][1]))\)\(i∈[1,n]\)。

回想一个性质,树上离某点i最远的点一定是树直径上两个端点中的一个。根据上面的式子,很明显令\(BC\)为树的直径时答案一定最优。接下来再按上面的方法去找个\(A\)就解决了。

时间复杂度为\(O(N)\)。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
struct node{int to,w;};
vector<node>e[N]; int id1,id2,n,m;
ll ma=0,g[N][2];
void dfs(int x,ll dis,int fa){
if(dis>ma)ma=dis,id1=x;
for(int i=0;i<e[x].size();i++){
int y=e[x][i].to;if(y==fa)continue;
dfs(y,dis+e[x][i].w,x);
}
}
void go(int x,ll dis,int fa,int o){
g[x][o]=dis;
for(int i=0;i<e[x].size();i++){
int y=e[x][i].to;if(y==fa)continue;
go(y,dis+e[x][i].w,x,o);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1,u,v,d;i<=m;i++){
scanf("%d%d%d",&u,&v,&d);
e[u].push_back((node){v,d});
e[v].push_back((node){u,d});
}
dfs(1,0,0);
id2=id1,ma=0;
dfs(id1,0,0); go(id1,0,0,0);go(id2,0,0,1);
ll now=0;
for(int i=1;i<=n;i++){
if(i==id1||i==id2)continue;
now=max(now,min(g[i][0],g[i][1]));
}
printf("%lld\n",now+ma);
}

[NOI2003]逃学的小孩【观察+树的直径】的更多相关文章

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

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

  2. LUOGU P4408 [NOI2003]逃学的小孩(树的直径)

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

  3. 洛谷P4408 [NOI2003] 逃学的小孩 (树的直径)

    本题就是从c到a/b再到b/a距离的最大值,显然,a和b分别是树的直径的两个端点,先用两次dfs求出树的直径,再用一次dfs求出每个点到a的距离,最后再用一次dfs求出每个点到距离它较近的a/b的距离 ...

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

    一边一定是直径,另一边从两端点走取最小值的最大值 #include <iostream> #include <cstdio> #include <cstring> ...

  5. NOI 2003 逃学的小孩 (树的直径)

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

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

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

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

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

  8. BZOJ1509: [NOI2003]逃学的小孩(树的直径)

    Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1126  Solved: 567[Submit][Status][Discuss] Description ...

  9. [NOI2003]逃学的小孩 (贪心+树的直径+暴力枚举)

    Input 第一行是两个整数N(3 <= N <= 200000)和M,分别表示居住点总数和街道总数.以下M行,每行给出一条街道的信息.第i+1行包含整数Ui.Vi.Ti(1<=Ui ...

随机推荐

  1. Delphi 第2课

    项目文件.dpr单元文件.pas--目标文件.dcu窗体文件.dfu begin 对象名.属性 对象名.方法end; 在delphi 自动提示控制语句结构 键盘输入Ctrl 就可以看到了 代码错误:( ...

  2. MongoDB4.0及以上的版本安装时无法启动服务。

    问题描述:MongoDB安装过程中启动服务失败,点击忽略之后,可以安装完成.安装完成之后提示重启电脑,出现电脑蓝屏. 并且修复好电脑之后无法启动MongoDB服务. 暂时不知道原因(怀疑是MongoD ...

  3. Java怎样判断身份证号

    判断身份证号是否正确使用的是正则,Java与js中使用正则的方式大差不差,下面是Java通过正则判断身份证号是否正确的 * */ @Test public void cardId() { System ...

  4. Java怎样获取字符串最后出现的位置

    lastIndexOf();表示获取字符串最后出现的位置,倒数的位置 @Test /** * lastIndexOf();//获取字符串最后出现的位置,倒数的位置 * */ public void f ...

  5. leetcode-50-pow()

    题目描述: 方法一: class Solution: def myPow(self, x: float, n: int) -> float: if n<0: x = 1/x return ...

  6. 概率dp——cf518D

    通过最后的概率求最终的期望 #include<bits/stdc++.h> using namespace std; ; double p,dp[maxn][maxn]; int n,t; ...

  7. python处理多线程之间事件通讯方法

    一.什么是事件 每执行一个事情,肯定有该事情的执行后状态,那事件就是该事情发生的信号 在程序中,多线程之间需要通讯,而事件就是方便线程之间的通讯 案例: 1.服务器启动需要5秒 2.客服端启动后去链接 ...

  8. UML之类图、时序图、用例图 粗略版介绍

    UML 概述 UML(Unified Modeling Language):统一(标准)建模语言,是一个支持模型化和软件系统开发的图形化语言,为软件开发的所有阶段提供模型化和可视化支持,包括由需求分析 ...

  9. mysql用户和权限

    1.创建用户 格式:grant 权限 on 数据库.* to 用户名@登录主机 identified by "密码" mysql>grant all privileges o ...

  10. 13-2-return

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...