Input

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

Output

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

输入输出样例

Intput:

4 3

1 2 1

2 3 1

3 4 1

Output:

4

开脑洞的时间到了:

花里胡哨的题干感觉是这题最难的地方了...

又是追捕又是搜查的,抓个逃课搞得跟缉毒一样(我也想逃课啊)

回归正题,从题目中给的描述中我们很容易能知道这是一棵树,还是双向的。

因为A和B的位置不确定(这也代表A、B只是象征性的,我们可以随意互换A、B的位置),为了让用时最长肯定让A和B离的最远,说白了就是要找到树的直径

关于贪心的合理性证明可以参见洛谷:传送门

A、B的用时最远了,我们还需要让出发点C最远,思路很明朗,在遍历时直接记录下每个点到A跟B的距离即可(前提是知道A和B,我们要先遍历一遍找到A跟B,再把数组清零重新遍历找距离)

找到所有的距离后,那么最后的答案就是:取每个点中到A或B的距离中较小的那一个距离(每个点应该有两个距离,到A一个、到B一个,我们取较小的那个),再在每个取出来的距离中取一个最大值,再加上直径,即为答案 (为什么要选较小的那个呢?题目要求我们先去离的近的那家) ,这句话我自己单看都绕不太懂,可以结合下面的代码看一看,能自己画个图模拟一下就更好了(下面给出了两种输出方案,但本质是一样的,都是我上边解释的这种,形式上方案2比较好理解)

(另外,不要忘记开long long...能全开就全开吧,我就是有的变量开了long long 有的没开结果翻了车...)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=200000+10;
#define ll long long
ll dis_A[maxn],dis_B[maxn],head[maxn],len=0;
ll zhijing=0;
int n,m,B,A;//这里的A、B只是个相对的概念,象征着直径的两端,毕竟题目中的A、B本身就可以互换
struct Edge{
int next,to,dis;
}edge[maxn<<1];
void Add(int a,int b,int c){
edge[++len].dis=c;
edge[len].to=b;
edge[len].next=head[a];
head[a]=len;
}
void Find_A(int u,int fa,int flag){//这个函数是用来找到每个点到A点的距离的
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to,w=edge[i].dis;
if(v==fa) continue;
dis_A[v]=dis_A[u]+w;
if(flag){ //我们手动设计一个开关,只有第一遍的时候我们才需要找到B,但实际上不加这个if应该没什么影响
if(dis_A[v]>dis_A[B]) B=v;
}
Find_A(v,u,flag);
}
}
void Find_B(int u,int fa,int flag){//同上,只不过要找的点变为另一端
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to,w=edge[i].dis;
if(v==fa)continue;
dis_B[v]=dis_B[u]+w;
if(flag) {
if(dis_B[v]>dis_B[A]) {
A=v;
zhijing=dis_B[v];
}
}
Find_B(v,u,flag);
}
}
int main(){
memset(dis_A,0,sizeof(dis_A));
memset(dis_B,0,sizeof(dis_B));
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
Add(u,v,w),Add(v,u,w);
}
Find_A(1,0,true);//第一遍遍历,我们要找到点A,也就是树的直径的一端
Find_B(B,0,true);//我们以找到的一端进行遍历,找到直径的另一端
ll ans=dis_B[A];//dis_B[A]其实就是直径,如果不明白可以取消掉下面的注释看一看 //printf("dis_A[B]=%d dis_B[B]=%d zhijing=%d\n",dis_A[B],dis_B[B],zhijing); memset(dis_A,0,sizeof(dis_A));//这里一定要归零,因为我们要重新计算距离
memset(dis_B,0,sizeof(dis_B));
Find_A(B,0,false);
Find_B(A,0,false); //输出方案1
/*ll cc=0;
for(int i=1;i<=n;i++){
ll d=min(dis_B[i],dis_A[i]);
if(d>cc) cc=d;
}
cout<<ans+cc<<endl;
*/ //输出方案2
/*
ll ans2=-999999999999;
for(int i=1;i<=n;i++){
ans2=max(ans2,min(dis_A[i],dis_B[i]));
}
cout<<ans2+zhijing<<endl;
*/ return 0;
}

[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]逃学的小孩【观察+树的直径】

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

随机推荐

  1. 初学python笔记

    一.关于python ① 由荷兰人Guido van Rossum(龟叔)于1989年圣诞节为打发无聊时间所编写的编程语言. ② python的特点:优雅 明确 简单.代码量少,运行速度快. 缺点:运 ...

  2. Swift 语法总结

    1,用 var 定义变量 ,与js类似. let 用于定义常量,定义完后不能修改. var 用于定义变量,可以修改. swift可以自动识别属性类别. 2,使用 import 语句来引入任何的 Obj ...

  3. 认识OSI七层模型

    概述: OSI全名(Open System Interconnect),是指定的开放系统互连参考模型,为开放式互连信息系统提供了一种功能结构的框架.层次:从低到高的层级:物理层.数据链路层.网络层.传 ...

  4. 源码分析 | 手写mybait-spring核心功能(干货好文一次学会工厂bean、类代理、bean注册的使用)

    作者:小傅哥 博客:https://bugstack.cn - 汇总系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言介绍 一个知识点的学习过程基本分为:运行helloworld ...

  5. 掌握SpringBoot-2.3的容器探针:实战篇

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:原创文章分类汇总,及配套源码,涉及Java.Docker.K8S.DevOPS等 经过多篇知识 ...

  6. JSP和Servlet的相同点和不同点、有何联系。

    JSP 和 Servlet 有哪些相同点和不同点,他们之间的联系是什么? 联系: JSP 是 Servlet 技术的扩展,本质上是 Servlet 的简易方式,更强调应用的外表表达. JSP编译后是& ...

  7. Codeforces Round #647 (Div. 2)

    Problem A https://codeforces.com/contest/1362/problem/A 判断x/y是不是2的k次方, 如果是 k/3 + (k%3)/2 + (k%3%2)即为 ...

  8. 数据库(mysql)基础操作

    DDL(数据定义语言)------>建库,建表 DML(数据操作语言)------>对表中的记录操作增删改查 DQL(数据查询语言)------>对表中的查询操作 DCL(数据控制语 ...

  9. cb27a_c++_STL_算法_最小值和最大值

    cb27a_c++_STL_算法_最小值和最大值min_element(b,e) b--begin(), e--end()min_element(b,e,op). op:函数,函数对象,一元谓词.ma ...

  10. new jup在新一代中存在

    1.灰度发布服务动态路由 动态配置路由规则,实现对调用流量的精确控制.可配置基于版本.IP.自定义标签等复杂的规则.2.服务鉴权示例2需求:服务 provider-demo 只允许来自 consume ...