[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,分别表示居住点总数和街道总数.以 ...
随机推荐
- Java基础(十)
一.XML概述 属性文件是用来描述程序配置,属性文件包含了一组名/值对.属性文件采用的是一种单一的平面层次结构,同时属性文件要求键是唯一的. XML格式能够表达层次结构,并且重复的元素不会被曲解. H ...
- Jmeter环境部署
一.安装jdk 下载jdk 双击jdk-8u211-windows-x64.exe,默认下一步安装 我的电脑-属性-高级系统设置-环境变量 在“系统变量”出,新建”JAVA_HOME”,配置jdk的安 ...
- Nice Jquery Validator 【从 jQuery Validation 迁移】
1. 初始化表单验证 .validate VS .validator jquery-validation : $("#myform").validate(options) nice ...
- 深入理解Js数组
深入理解Js数组 在Js中数组存在两种形式,一种是与C/C++等相同的在连续内存中存放数据的快数组,另一种是HashTable结构的慢数组,是一种典型的字典形式. 描述 在本文中所有的测试都是基于V8 ...
- python flask API 返回状态码
@app.route('/dailyupdate', methods = ['POST','GET'])def dailyUpdate(): try: db=MySQLdb.connect(" ...
- 关于MYSQL的查询时间段、删除数据、查询目标行的命令用法。
Q1.第一次工作写命令时,写了一个把一个表的数据插入到另一个表中,运行时命令长时间处于执行状态. A.第一次处理数据库大量数据,长时间按运行属于正常现象,这与学校中的小数据不同. Q2.如何查询数据库 ...
- cb49a_c++_STL_算法_对所有元素排序_sort_stable_sort
cb49a_c++_STL_算法_对所有元素排序_sort_stable_sort sort(b,e) sort(b,e,p) stable_sort(b,e) stable_sort(b,e,p) ...
- Appium 自动化实例代码
自动化连接 B站 开始 如果下载node.js 的话 可以检查一下appium环境 命令行: appium-doctor 如果没有 可以安装 appium-doctor :npm install ...
- Beta冲刺<5/10>
这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺--第五天(05.23) 作业正文 如下 其他参考文献 ... B ...
- django drf插件(一)
复习 """ 1.vue如果控制html 在html中设置挂载点.导入vue.js环境.创建Vue对象与挂载点绑定 2.vue是渐进式js框架 3.vue指令 {{ }} ...