[BZOJ1509][NOI2003]逃学的小孩
Description
Input
第一行是两个整数N(3 N 200000)和M,分别表示居住点总数和街道总数。以下M行,每行给出一条街道的信息。第i+1行包含整数Ui、Vi、Ti(1Ui, 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
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; }