LUOGU P4408 [NOI2003]逃學的小孩(樹的直徑)

題目描述

Chris家的電話鈴響起了,裏面傳出了Chris的老師焦急的聲音:「喂,是Chris的家長嗎?大家的孩子又沒來上課,不想參加考試了嗎?」一據說要考試,Chris的父母就心急如焚,他們決定在儘可能短的時間內找到Chris。他們告訴Chris的老師:「根據以往的經驗,Chris如今必然躲在朋友Shermie或Yashiro家裏偷玩《拳皇》遊戲。如今,咱們就從家出發去找Chris,一但找到,咱們馬上給您打電話。」說完砰的一聲把電話掛了。c++

Chris居住的城市由N個居住點和若干條鏈接居住點的雙向街道組成,通過街道x需花費Tx分鐘。能夠保證,任兩個居住點間有且僅有一條通路。Chris家在點C,Shermie和Yashiro分別住在點A和點B。Chris的老師和Chris的父母都有城市地圖,但Chris的父母知道點A、B、C的具體位置而Chris的老師不知。git

爲了儘快找到Chris,Chris的父母會遵照如下兩條規則:spa

  1. 若是A距離C比B距離C近,那麼Chris的父母先去Shermie家尋找Chris,若是找不到,Chris的父母再去Yashiro家;反之亦然。
  2. Chris的父母總沿着兩點間惟一的通路行走。

顯然,Chris的老師知道Chris的父母在尋找Chris的過程當中會遵照以上兩條規則,但因爲他並不知道A,B,C的具體位置,因此如今他但願你告訴他,最壞狀況下Chris的父母要耗費多長時間才能找到Chris?code

輸入輸出格式

輸入格式:

 

輸入文件第一行是兩個整數N(3 ≤ N ≤ 200000)和M,分別表示居住點總數和街道總數。blog

如下M行,每行給出一條街道的信息。第i+1行包含整數Ui、Vi、Ti(1≤Ui, Vi ≤ N,1 ≤ Ti ≤ 1000000000),表示街道i鏈接居住點Ui和Vi,而且通過街道i需花費Ti分鐘。街道信息不會重複給出。遊戲

 

輸出格式:

 

輸出文件僅包含整數T,即最壞狀況下Chris的父母須要花費T分鐘才能找到Chris。get

 

輸入輸出樣例

輸入樣例#1:  複製
4 3
1 2 1
2 3 1
3 4 1
輸出樣例#1:  複製
4

解析:it

用SPFA作樹的直徑,與普通的SPFA大體相同,只要在最後加上一重for循環記錄距離最大的點便可;io

求樹的直徑是隻要作兩遍SPFA就能夠了;for循環

#include<bits/stdc++.h>
using namespace std;
#define rint register int 
#define ll long long

inline int read(){
    int x=0,f=0;char ch=getchar();
    while(!isdigit(ch))    f=(ch==45),ch=getchar();
    while( isdigit(ch))    x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?(~x+1):x;
}

#define man 200050

struct edge{int next,to,dis;}e[man<<1];
int head[man<<1],num=0;

inline void add(int from,int to,int dis){
    e[++num]=(edge){head[from],to,dis};
    head[from]=num;
}
int n,m; int vis[man]; ll dis0[man],disa[man],disb[man]; inline int spfa(int s,ll dis[]){ for(rint i=1;i<=n;i++) dis[i]=2e11+9,vis[i]=0; queue<int>q; q.push(s);dis[s]=0;vis[s]=1; do{ int u=q.front();q.pop();vis[u]=0; for(rint i=head[u];i;i=e[i].next){ int to=e[i].to; if(dis[to]>dis[u]+e[i].dis){ dis[to]=dis[u]+e[i].dis; if(!vis[to]){ vis[to]=1; q.push(to); } } } }while(!q.empty()); ll maxn=0;int pos=s; for(rint i=1;i<=n;i++){ if(maxn<dis[i]) maxn=dis[i],pos=i; } return pos; } int main(){ n=read();m=read(); for(rint i=1,x,y,z;i<=m;i++){ x=read();y=read();z=read(); add(x,y,z);add(y,x,z); } rint a=spfa(1,dis0); rint b=spfa(a,disa); spfa(b,disb); ll ans=disa[b],maxn=0; for(rint i=1;i<=n;i++) maxn=max(maxn,min(disa[i],disb[i])); printf("%lld\n",ans+maxn); return 0; }
相關文章
相關標籤/搜索