1. 程式人生 > >[NOI2003]逃學的小孩

[NOI2003]逃學的小孩

char 根據 esp 連接 print put tput 參加 小孩

題目描述

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的父母會遵守以下兩條規則:

  1. 如果A距離C比B距離C近,那麽Chris的父母先去Shermie家尋找Chris,如果找不到,Chris的父母再去Yashiro家;反之亦然。
  2. 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。

此題很容易看出是要先求樹的直徑,然後的操作我一開始的思路有些錯誤。

一開始我的想法是在直徑上找一個點作為起點,在dfs的過程中記錄下直徑的路徑和權值road,

把road數組前綴和化,於是答案就是lenth+max{min(lenth-road[i],road[i])};

但是在WA掉以後,我發現起點不在直徑上也許會更好,於是我們用SPFA求出,每個點到直徑兩端的距離

那麽答案就是lenth+max{min(dis[0][i],dis[1][i])};

實現如下:

#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long ll;
inline ll read()
{
    register ll p(1),a(0);register char ch=getchar();
    while((ch<0||ch>9)&&ch!=-) ch=getchar();
    if(ch==-) p=-1,ch=getchar();
    while(ch>=0&&ch<=9) a=a*10+ch-48,ch=getchar();
    return a*p;
}
const int N=200010;
int n,m,u,v,head[N],cnt=0,zq,zz,len=0,book[N];
ll ans=0,w,maxn=0,road[N],dis[2][N];
struct EDGE{int nxt,to;ll val;}e[N<<1];
void add(int u,int v,ll w){e[++cnt]=(EDGE){head[u],v,w};head[u]=cnt;}
void dfs(int u,int fa,ll siz)
{
    if(siz>maxn){maxn=siz;zq=u;}
    for(int i=head[u],v=e[i].to;i;i=e[i].nxt,v=e[i].to) if(fa!=v) dfs(v,u,siz+e[i].val);
}
queue<int> Q;
void SPFA(int u,int pre)
{
    memset(dis[pre],0x3f,sizeof(dis[pre]));
    memset(book,0,sizeof(book));
    Q.push(u);dis[pre][u]=0;book[u]=1;
    while(!Q.empty())
    {
        u=Q.front();Q.pop();book[u]=0;
        for(int i=head[u],v=e[i].to;i;i=e[i].nxt,v=e[i].to)
            if(dis[pre][v]>dis[pre][u]+e[i].val)
            {
                dis[pre][v]=dis[pre][u]+e[i].val;
                if(!book[v]) Q.push(v);
            }
    }
}
int main()
{
    // freopen("input","r",stdin);
    // freopen("output","w",stdout);
    n=read(),m=read();
    for(int i=1;i<=m;i++)
    {
        u=read(),v=read(),w=read();
        add(u,v,w);add(v,u,w);
    }
    dfs(1,-1,0);zz=zq,maxn=0;
    dfs(zq,-1,0);
    SPFA(zz,0);SPFA(zq,1);
    for(int i=1;i<=n;i++) ans=max(ans,min(dis[0][i],dis[1][i]));
    printf("%lld\n",ans+maxn);
    return 0;
}

[NOI2003]逃學的小孩