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遇到Excel后,将开启你的认知虫洞

    本文主要内容:   1. Excel,你为什么如此强大 2. 软件开发也需要团队作战 3. Excel的集成方案演化 4. macOS特有的集成方案:applescript 5. Python与Exc ...

  2. Jmeter之Json提取器详解(史上最全)

    参考资料:https://www.bbsmax.com/A/D854lmBw5E/ Jsonpath在线测试:http://jsonpath.com/ 实际工作中用到的一些场景: 提取某个特定的值 提 ...

  3. java关键字volatile用法详解

    volatile关键字想必大家都不陌生,在java 5之前有着挺大的争议,在java 5之后才逐渐被大家接受,同时作为java的关键字之一,其作用自然是不可小觑的,要知道它是java.util.con ...

  4. ReentrantLock原理分析

    一 UML类图 通过类图ReentrantLock是同步锁,同一时间只能有一个线程获取到锁,其他获取该锁的线程会被阻塞而被放入AQS阻塞队列中.ReentrantLock类继承Lock接口:内部抽象类 ...

  5. Html/css 水平布局居中

    如何设置水平居中显示? 一般的方法是设置宽高,然后以margin去控制,比如:DIV居中的经典方法 本章介绍需要宽度自适应时如何水平居中,以及居中失效的几个点 水平自适应居中 比如设置一个列表水平居中 ...

  6. jenkins环境安装(windows)

    一.简介 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能.   二. Jenkins功能 1. ...

  7. JPA 中 find() 和 getReference() 的区别

    在查询的时候有两个方法:find()和getReference(),这两个方法的参数以及调用方式都相同.那么这两个方法有什么不一样的呢? find()称为 立即加载,顾名思义就是在调用的时候立即执行查 ...

  8. Fabric网络节点发现及成员管理

    一个新节点通过已知的节点加入到网络中,此时,它所知的网络节点信息是非常有限的,需要通过节点发现获知更多的节点,建立起足够的连接.另外,当一个新节点加入到网络时,原有网络节点也需要通过节点发现感知到新节 ...

  9. 初识Redis的数据类型HyperLogLog

    前提 未来一段时间开发的项目或者需求会大量使用到Redis,趁着这段时间业务并不太繁忙,抽点时间预习和复习Redis的相关内容.刚好看到博客下面的UV和PV统计,想到了最近看书里面提到的HyperLo ...

  10. docker配置国内镜像地址,解决无法pull镜像问题docker: Error response from daemon

    问题: 执行命令 $ docker run -it --rm -p 8888:8080 tomcat:8.5.32 报错 Unable to find image 'tomcat:8.5.32' lo ...