「NOI2003」逃学的小孩

传送门:>HERE<

题意:给出一棵树(带权),要从一个节点C先走到距离它近的一个节点B,再走到A,要求最坏情况下的总路程(即最长)。

解题思路:

  乍一看,A,B,C都没给出,这怎么求?

  不妨设距离C较近的点位A。

  分析发现,无论怎样,A~B是一定要走的。那么如何能让树上任意两点间距离最大呢?不难发现A,B就是该树直径的两个端点。那么只要两遍BFS就好了。

  那么如何让A~C的路程最长呢?注意到A到C相较A到B是较短的。所以好像不怎么好求……但是可以枚举——枚举每个点作为C到A和B的距离,求出较小的那个,并且打擂得到最大值。

Code

/*By QiXingzhi*/
#include <cstdio>
#include <queue>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#define  r  read()
#define  Max(a,b)  (((a)>(b)) ? (a) : (b))
#define  Min(a,b)  (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
#define int ll
const int N = 200010;
const int INF = 1061109567;
inline int read(){
    int x = 0; int w = 1; register int c = getchar();
    while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
    if(c == '-') w = -1, c = getchar();
    while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar();
    return x * w;
}
struct Edge{
    int to,cost;
};
int n,m,x,y,z,A,B,ans,ans2;
int d[N], d2[N], vis[N];
vector <Edge> G[N];
queue <int> q;
inline void AddEdge(int u, int v, int w){
    Edge e;
    e.to = v;
    e.cost = w;
    G[u].push_back(e);
}
inline void BFS(int s){
    while(!q.empty()) q.pop();
    q.push(s);
    d[s] = 0;
    vis[s] = 1;
    int cur,sz,v;
    while(!q.empty()){
        cur = q.front();
        q.pop();
        sz = G[cur].size();
        for(int i = 0; i < sz; ++i){
            v = G[cur][i].to;
            if(!vis[v]){
                vis[v] = 1;
                d[v] = d[cur] + G[cur][i].cost;
                q.push(v);
            }
        }
    }
}
inline void BFS2(int s){
    while(!q.empty()) q.pop();
    q.push(s);
    d2[s] = 0;
    vis[s] = 1;
    int cur,sz,v;
    while(!q.empty()){
        cur = q.front();
        q.pop();
        sz = G[cur].size();
        for(int i = 0; i < sz; ++i){
            v = G[cur][i].to;
            if(!vis[v]){
                d2[v] = d2[cur] + G[cur][i].cost;
                vis[v] = 1;
                q.push(v);
            }
        }
    }
}
main(){
    n = r, m = r;
    for(int i = 1; i <= m; ++i){
        x = r, y = r, z = r;
        AddEdge(x, y, z);
        AddEdge(y, x, z);
    }
    BFS(1);
    int __max = -100;
    for(int i = 1; i <= n; ++i){
        if(d[i] > __max){
            __max = d[i];
            A = i;
        }
    }
    ans = __max;
    memset(vis,0,sizeof(vis));
    BFS(A);
    __max = -100;
    for(int i = 1; i <= n; ++i){
        if(d[i] > __max){
            __max = d[i];
            B = i;
        }
    }
    ans = __max;
    memset(vis,0,sizeof(vis));
    BFS2(B);
    for(int i = 1; i <= n; ++i) ans2 = Max(ans2, Min(d[i], d2[i]));
    printf("%lld", ans+ans2);
    return 0;
}
原文地址:https://www.cnblogs.com/qixingzhi/p/9342138.html