zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    判断回溯法中的标记数组vis在回溯的时候是否要取消标记?
    Linux多线程开发I
    答题小程序开发
    答题活动小程序
    今天来谈谈答题小程序的上下游生态
    挑战答题小程序V2.0
    可以免费出题的答题小程序
    挑战答题小程序上线了
    通过小程序反编译来谈谈小程序的分包加载机制?
    本文介绍下答题小程序V6.0
  • 原文地址:https://www.cnblogs.com/BriMon/p/9404204.html
Copyright © 2011-2022 走看看