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

[BZOJ1509][NOI2003]逃學的小孩

div 最壞情況 size git print src alt isa ron

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\n", ans1 + ans2); return 0; }

[BZOJ1509][NOI2003]逃學的小孩