[NOI2003]逃學的小孩(樹的直徑)
[NOI2003]逃學的小孩
題目描述
Chris家的電話鈴響起了,裏面傳出了Chris的老師焦急的聲音:“餵,是Chris的家長嗎?你們的孩子又沒來上課,不想參加考試了嗎?”一聽說要考試,Chris的父母就心急如焚,他們決定在盡量短的時間內找到Chris。他們告訴Chris的老師:“根據以往的經驗,Chris現在必然躲在朋友Shermie或Yashiro家裏偷玩《拳皇》遊戲。現在,我們就從家出發去找Chris,一但找到,我們立刻給您打電話。”說完砰的一聲把電話掛了。
Chris居住的城市由N個居住點和若幹條連接居住點的雙向街道組成,經過街道x需花費Tx分鐘。可以保證,任兩個居住點間有且僅有一條通路。Chris家在點C,Shermie和Yashiro分別住在點A和點B。Chris的老師和Chris的父母都有城市地圖,但Chris的父母知道點A、B、C的具體位置而Chris的老師不知。
為了盡快找到Chris,Chris的父母會遵守以下兩條規則:
- 如果A距離C比B距離C近,那麽Chris的父母先去Shermie家尋找Chris,如果找不到,Chris的父母再去Yashiro家;反之亦然。
- Chris的父母總沿著兩點間唯一的通路行走。
顯然,Chris的老師知道Chris的父母在尋找Chris的過程中會遵守以上兩條規則,但由於他並不知道A,B,C的具體位置,所以現在他希望你告訴他,最壞情況下Chris的父母要耗費多長時間才能找到Chris?
輸入輸出格式
輸入格式:
輸入文件第一行是兩個整數N(3 ≤ N ≤ 200000)和M,分別表示居住點總數和街道總數。
以下M行,每行給出一條街道的信息。第i+1行包含整數Ui、Vi、Ti(1≤Ui, Vi ≤ N,1 ≤ Ti ≤ 1000000000),表示街道i連接居住點Ui和Vi,並且經過街道i需花費Ti分鐘。街道信息不會重復給出。
輸出格式:
輸出文件僅包含整數T,即最壞情況下Chris的父母需要花費T分鐘才能找到Chris。
輸入輸出樣例
輸入樣例#1: 復制
4 3
1 2 1
2 3 1
3 4 1
輸出樣例#1: 復制
4
題解
數據太水了?
雖然A了,但是我的代碼是錯誤的,巨佬自行修改一下(懶得改了)。
求出樹直徑的起點和終點。
處理出每個點對於起點和終點的兩個距離。
然後掃一遍求出直徑上的點求出較短半徑即可。
代碼
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<queue> #define ll long long using namespace std; const int N=200001; struct node{ int nex,to; ll v; }e[N]; ll n,m,root,ans,maxx; ll dis[N],num,head[N]; ll disr[N],s,t; ll read(){ ll x=0,w=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*w; } void add(int from,int to,ll v){ num++; e[num].to=to; e[num].v=v; e[num].nex=head[from]; head[from]=num; } void dfs(int x,int fa){ for(int i=head[x];i;i=e[i].nex){ int v=e[i].to;if(v==fa)continue; dis[v]=dis[x]+e[i].v;dfs(v,x); } } void dfs2(int x,int fa){ for(int i=head[x];i;i=e[i].nex){ int v=e[i].to;if(v==fa)continue ; disr[v]=disr[x]+e[i].v;dfs2(v,x); } } int main(){ n=read();m=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(),z=read(); add(x,y,z);add(y,x,z); } dfs(1,1); for(int i=1;i<=n;i++) {if(dis[i]>maxx)s=i,maxx=dis[i];dis[i]=0;} dfs(s,0);maxx=0; for(int i=1;i<=n;i++) if(dis[i]>maxx)t=i,maxx=dis[i]; dfs2(t,0); for(int i=1;i<=n;i++) if(i!=s&&i!=t) ans=max(ans,min(dis[i],disr[i])); printf("%lld\n",ans+maxx); return 0; }
[NOI2003]逃學的小孩(樹的直徑)