[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,分别表示居住点总数和街道总数.以 ...
随机推荐
- Python爬虫 爬取搜狗搜索到的内容页面
废话不多说,直接上代码 import requests def main(): url='https://www.sogou.com/web' headers={ 'User_Agent':'Mozi ...
- centos 7 c++连接mysql的常用函数说明及使用样例
以下函数使用之前需安装mysql,并包含mysql.h头文件,设置好mysqlclient动态库 一.mysql_init() MYSQL * mysql_init(MYSQL *mysql); // ...
- 【百度前端学院 Day4】背景边框列表链接和更复杂的选择器
1. 背景 背景指的是元素内容.内边距和边界下层的区域(可用background-clip修改) background-color 背景色 background-image 背景图片(url) b ...
- public、potected 、private继承下的子类对父类成员的访问情况
#include<iostream> #include<string> using namespace std; class parent{ protected: int m_ ...
- WinForm通用自动更新AutoUpdater项目实战
目前我们做的上位机项目还是以Winform为主,在实际应用过程中,可能还会出现一些细节的修改.对于这种情况,如果上位机带有自动更新功能,我们只需要将更新后的应用程序打包放在指定的路径下,可以让用户自己 ...
- 微信weixin://xxx 分析
通过weixin://来打开微信客户端: <a href="weixin://">打开微信</a> <a href="weixin://dl ...
- RabbitMQ系列之【启动过程中遇到问题及解决方案】
1.如果显示找不到主机,请在hosts文件中添加: vi /etc/hosts 127.0.0.1 localhost 2.从3.3.1版本开始,RabbitMQ默认不允许远程ip登录,即只能使用lo ...
- MFC的Spin Control基础控件的使用
1.向GUI界面添加一个MFC 提供的Spin数值调节控件 2.设置其"伙伴“,并设置数值调节的范围 3.如何让数值显示在文本框中?你可以有多种选择:可以让文本框控件绑定一个数值类型的变量: ...
- SQLserver 的分页存储过程
-- 1.建立修改学生数据的存储过程 -- 2.建立根据班级Id和学生姓名模糊查询的分页存储过程,要求正确输出总记录数,总页数-- (输入班学生姓名 计算总记录数 计算总页数) -- @name ...
- MySQL服务器是怎么处理客户端请求的
不论MySQL客户端进程和服务器进程是采用哪种方式进行通信,最后实现的效果都是:客户端进程向服务器进程发送一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果).那服务器进 ...