[BZOJ1509][NOI2003]逃学的小孩

Description

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。

Sample Input

4 3
1 2 1
2 3 1
3 4 1

Sample Output

4


肯定会选树的直径,然后其他点枚举一下,取到直径两端距离的最小值的最大值,然后加上树的直径就是答案。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
using namespace std;
#define int long long
#define g getchar()
#define i isdigit(ch)
inline int read(){
    int res=0;char ch=g;
    while(!i) ch=g;
    while(i) {res=(res<<3)+(res<<1)+(ch^48);ch=g;}
    return res;
}
#undef g
#undef i
#define N 200005
int n, m;
struct edge{
    int nxt, to, val;
}ed[N*2];
int head[N], cnt;
inline void add(int x, int y, int z)
{
    ed[++cnt] = (edge){head[x], y, z};
    head[x] = cnt;
}

int dis[N], disa[N], disb[N];
int p1, p2;
int ans1, ans2;
bool ex[N];

void dfs(int x)
{
    ex[x] = 1;
    for (int i = head[x] ; i ; i = ed[i].nxt)
    {
        int to = ed[i].to;
        if (ex[to]) continue;
        dis[to] = dis[x] + ed[i].val;
        dfs(to);
    }
}

inline void SPFA1(int cur)
{
    memset(ex, 0, sizeof ex);
    memset(disa, 0x3f, sizeof disa);
    disa[cur] = 0;
    queue <int> q;
    q.push(cur);
    while(!q.empty())
    {
        int x = q.front();q.pop();
        ex[x] = 0;
        for (int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (disa[to] > disa[x] + ed[i].val)
            {
                disa[to] = disa[x] + ed[i].val;
                if (!ex[to])
                {
                    ex[to] = 1;
                    q.push(to);
                }
            }
        }
    }
}

inline void SPFA2(int cur)
{
    memset(ex, 0, sizeof ex);
    memset(disb ,0x3f, sizeof disb);
    disb[cur] = 0;
    queue <int> q;
    q.push(cur);
    while(!q.empty())
    {
        int x = q.front();q.pop();
        ex[x] = 0;
        for (int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (disb[to] > disb[x] + ed[i].val)
            {
                disb[to] = disb[x] + ed[i].val;
                if (!ex[to])
                {
                    ex[to] = 1;
                    q.push(to);
                }
            }
        }
    }
}

signed 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);
    p1 = 1;
    for (int i = 1 ; i <= n ; i ++) if (dis[i] > dis[p1]) p1 = i;
    memset(dis, 0, sizeof dis);
    memset(ex, 0, sizeof ex);
    dfs(p1);
    p2 = 1;
    for (int i = 1 ; i <= n ; i ++) if (dis[i] > dis[p2]) p2 = i;
    SPFA1(p1);
    SPFA2(p2);
    ans1 = disa[p2];
    for (int i = 1 ; i <= n ; i ++)
        ans2 = max(ans2, min(disa[i], disb[i]));
    printf("%lld
", ans1 + ans2);    
    return 0;
}
原文地址:https://www.cnblogs.com/BriMon/p/9404204.html