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

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]逃学的小孩 (贪心+树的直径+暴力枚举)的更多相关文章
- [NOI2003]逃学的小孩(树的直径)
[NOI2003]逃学的小孩 题目描述 Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:"喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?"一听 ...
- LUOGU P4408 [NOI2003]逃学的小孩(树的直径)
题目描述 Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:“喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?”一听说要考试,Chris的父母就心急如焚,他们决定在尽 ...
- 洛谷P4408 [NOI2003] 逃学的小孩 (树的直径)
本题就是从c到a/b再到b/a距离的最大值,显然,a和b分别是树的直径的两个端点,先用两次dfs求出树的直径,再用一次dfs求出每个点到a的距离,最后再用一次dfs求出每个点到距离它较近的a/b的距离 ...
- Luogu4408 [NOI2003]逃学的小孩 (树的直径)
一边一定是直径,另一边从两端点走取最小值的最大值 #include <iostream> #include <cstdio> #include <cstring> ...
- NOI 2003 逃学的小孩 (树的直径)
[NOI2003 逃学的小孩] 题目描述 Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:"喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?"一 ...
- 【BZOJ1509】[NOI2003]逃学的小孩 直径
[BZOJ1509][NOI2003]逃学的小孩 Description Input 第一行是两个整数N(3 N 200000)和M,分别表示居住点总数和街道总数.以下M行,每行给出一条街道的 ...
- BZOJ 1509: [NOI2003]逃学的小孩( 树形dp )
树形dp求出某个点的最长3条链a,b,c(a>=b>=c), 然后以这个点为交点的最优解一定是a+2b+c.好像还有一种做法是求出树的直径然后乱搞... ----------------- ...
- BZOJ1509: [NOI2003]逃学的小孩(树的直径)
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1126 Solved: 567[Submit][Status][Discuss] Description ...
- [NOI2003]逃学的小孩【观察+树的直径】
Online Judge:Bzoj1509,Luogu P4408 Label:观察,树的直径 题目描述 输入 第一行是两个整数N(\(3≤N≤200000\))和M,分别表示居住点总数和街道总数.以 ...
随机推荐
- MAC抓包工具Charles安装及破解
参考资料:https://juejin.im/post/5c0a430f51882516207d205d 下载 Charles官网下载安装包,下载成功后根据指示安装即可 官网地址:http://www ...
- Linux: 如何分割文件,不再被 4G 大小限制了
单文件 4G 限制 FAT32 4G 限制 百度网盘超出 4G 限制 单文件分割与合并 单文件,如:archive.tar.gz 分割 split -b 3000M -d -a 1 archive.t ...
- rgb格式颜色与#000000格式颜色的转换
首先,#000000格式的颜色被成为十六进制颜色码: 6位数分为三组,每两位数一组,依次是红.黄.蓝颜色的强度: 而与此对应的,rgb(39,137,202)依次是十进制的红黄蓝颜色: 因此将rgb格 ...
- MySQL触发器的详细教学与综合分析
所有知识体系文章,GitHub已收录,欢迎老板们前来Star! GitHub地址: https://github.com/Ziphtracks/JavaLearningmanual MySQL触发器 ...
- 【Spring注解驱动开发】在@Import注解中使用ImportSelector接口导入bean
写在前面 在上一篇关于Spring的@Import注解的文章<[Spring注解驱动开发]使用@Import注解给容器中快速导入一个组件>中,我们简单介绍了如何使用@Import注解给容器 ...
- 键盘鼠标共享效率工具----Synergy
在日常工作中,为了提高工作效率以及用户体验,会一个主机接多个显示器,像程序员一般都是使用两块显示器. 然而,有很多人是和我一样,自己有多台电脑,两个笔记本.公司一个台式机,如何在台机器之间来回切换工作 ...
- 微信小程序session_key解析中反斜杠问题处理 Java解析
Java服务端微信小程序解密用户信息.手机号需用到session_key也需要decode,以下是官方描述: 加密数据解密算法 接口如果涉及敏感数据(如wx.getUserInfo当中的 openId ...
- AIO,BIO,NIO,IO复用,同步,异步,阻塞和非阻塞
(1)什么是NIO(Non-blocked IO),AIO,BIO (2) 区别 (3)select 与 epoll,poll区别 1.什么是socket?什么是I/O操作? 什么是socket? 实 ...
- Beta冲刺<3/10>
这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺--第三天(05.21) 作业正文 如下 其他参考文献 ... B ...
- 一分钟开始持续集成之旅系列之:C 语言 + Makefile
作者:CODING - 朱增辉 前言 make 工具非常强大,配合 makefile 文件可以实现软件的自动化构建,但是执行 make 命令依然需要经历手动输入执行.等待编译完成.将目标文件转移到合适 ...