【图论】B065_AW_逃学的小孩(spfa最短路+树直径)

克里斯再次逃学去朋友家里玩了,生气的克里斯的父母决定把他给捉回来。
他的父母深知克里斯一定是在夏尔米或者七枷社家里玩。
克里斯所在的城市由N个居住点和M条连接居住点的双向街道组成,经过街道x需要花费Tx分钟。
可以保证,任意两个居住点之间有且仅有一条通路。
克里斯家在点C,夏尔米和七枷社家分别在点A和点B。

为了尽快找到克里斯,他的父母在寻找他时将遵守如下两条规则:

  1. 如果A距离C比B距离C近,则他的父母先到夏尔米家去找他,如果找不到,再去七枷社家。反之亦然。
  2. 克里斯的父母总沿着两点间唯一的通路行走。

但是我们并不知道A、B、C三个点的具体位置。请你计算在最坏的情况下,克里斯的父母要花多久才能找到他?

输入格式
第一行包含两个整数N和M。
接下来M行,每行包含三个整数u,v,t,表示居住点u和居住点v之间存在一条街道,且经过该街道需要花费t分钟。
街道信息不会重复给出。
输出格式
输出一个整数,表示克里斯父母在最坏的情况下,找到他需要花费的分钟数。
数据范围
3≤N≤200000,
1≤u,v≤N,
1≤t≤1000000000

输入样例:
4 3
1 2 1
2 3 1
3 4 1
输出样例:
4
方法一:spfa最短路+树直径

题意:求最大化的 max(min(C->A, C->B) + A->B):

  • min(C->A, C->B) 是最短距离中的最大者;证明:如果不是 C->A 的最短距离中的最大者,那从 C 出发,可能有更大的距离到 A(比如绕个 x 圈在到 A),这个 x 是个未知数故,结果不符。
  • max(A->B) 两个点最长路径就是树的直径
#include
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll n,m,inq[N],inf=0x3f3f3f3f;
struct node{
     
    ll u, w;
};
vector<node> g[N];
int spfa(int s, vector<ll>& d) {
     
    d.resize(n+5, inf);
    queue<int> q; q.push(s), d[s]=0;

    while (!q.empty()) {
     
        int u=q.front(); q.pop(), inq[u]=false;
        for (auto& to : g[u]) {
     
            int v=to.u, w=to.w;
            if (d[v]>d[u]+w) {
     
                d[v]=d[u]+w;
                if (!inq[v]) {
     
                    q.push(v);
                    inq[v]=true;
                }
            }
        }
    }
    ll mx=0, ans=0;
    for (int i=1; i<=n; i++) if (d[i]>mx)
        mx=d[i], ans=i;
    return ans;
}
int main() {
     
    std::ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for (int i=0; i<m; i++) {
     
        int u,v,t; cin>>u>>v>>t;
        g[u].push_back({
     v,t});
        g[v].push_back({
     u,t});
    }
    vector<ll> d1(n+5, (ll)inf*(ll)inf), d2(n+5, (ll)inf*(ll)inf);
    int A=spfa(1, d1);  //最远点A
    d1=vector(n+5, inf*inf);
    int B=spfa(A, d1);  //距离A的最远点B
    spfa(B, d2);        //从A到某个点的最短路已经求出,但以B为起点的最短路尚未求出,故再跑一边
    
    ll max_in_min=0;
    for (int C=1; C<=n; C++)
        max_in_min=max(max_in_min, min(d1[C],d2[C]));
    cout << max_in_min+d1[B];
    return 0;
}

复杂度分析

  • Time O ( ) O() O()
  • Space O ( ) O() O()

你可能感兴趣的:(【图论】B065_AW_逃学的小孩(spfa最短路+树直径))