1. 程式人生 > >「NOIP 2015」運輸計劃

「NOIP 2015」運輸計劃

題意 ret 需要 spl memset nchar noip color register

「題意」

  給 $n(\le 300000)$ 個點的樹,經過每條邊需要花費時間 $c$ 。

  有 $m(\le 300000)$ 個運輸計劃,將某條邊變為蟲洞,花費 $0$ 的時間,最小化最大花費時間。

「分析」

  二分最大花費時間 $x$ 。

  設 $S$ 為花費大於 $x$ 的路徑的集合,$M$ 為路徑花費減去 $x$ 的最大值。一條邊權為 $c$ 的邊可以變為蟲洞,當且僅當屬於 $S$ 中所有路徑的並,且 $c \ge M$ 。

  通過樹形 DP ,判斷一條邊是不是所有路徑的並。

「實現」

  1 #include <cstdio>
  2 #include <cstring>
  3
#include <cstdlib> 4 #include <cctype> 5 #include <cmath> 6 #include <ctime> 7 #include <algorithm> 8 using namespace std; 9 #define F(i, a, b) for (register int i = (a), _b = (b); i <= _b; i++) 10 #define D(i, a, b) for (register int i = (a), _b = (b); i >= _b; i--) 11
#define fore(x) for (register int k = hd[x], v; k > 0; k = mp[k].nx) if ((v = mp[k].v) != par[x]) 12 13 const int S = 10000000; 14 char s[S], *h = s+S, *t = h; 15 inline char nchar(void) { if (h == t) fread(s, 1, S, stdin), h = s; return *h++; } 16 inline int rd(void) { 17 int f = 1; char c = nchar(); for
(; !isdigit(c); c = nchar()) if (c == -) f = -1; 18 int x = 0; for (; isdigit(c); c = nchar()) x = x*10+c-0; return x*f; 19 } 20 21 const int N = 300005; 22 23 int n; 24 struct E { 25 int v, d, nx; 26 }mp[2*N]; 27 int tot, hd[N]; 28 29 int dep[N], dis[N], w[N], par[N], siz[N], son[N]; 30 int top[N]; 31 32 void Son(int x) { 33 siz[x] = 1; 34 fore(x) { 35 dep[v] = dep[x] + 1, dis[v] = dis[x] + mp[k].d, w[v] = mp[k].d, par[v] = x; 36 Son(v); 37 siz[x] += siz[v]; 38 if (siz[son[x]] < siz[v]) son[x] = v; 39 } 40 } 41 void spl(int x, int anc) { 42 top[x] = anc; 43 if (son[x] > 0) spl(son[x], anc); 44 fore(x) if (v != son[x]) 45 spl(v, v); 46 } 47 inline int LCA(int x, int y) { 48 while (top[x] != top[y]) 49 dep[top[x]] > dep[top[y]] ? x = par[top[x]] : y = par[top[y]]; 50 return dep[x] <= dep[y] ? x : y; 51 } 52 53 int m, u[N], v[N], anc[N]; 54 int idx, d[N]; 55 56 void run(int x) { 57 fore(x) 58 run(v), d[x] += d[v]; 59 } 60 int Deq(int x) { 61 int Max = 0; 62 idx = 0, memset(d, 0, sizeof d); 63 F(i, 1, m) { 64 int L = dis[u[i]] + dis[v[i]] - 2 * dis[anc[i]]; 65 if (L > x) idx++, d[u[i]]++, d[v[i]]++, d[anc[i]] -= 2, Max = max(Max, L-x); 66 } 67 run(1); 68 F(i, 1, n) if (d[i] == idx && w[i] >= Max) 69 return 1; 70 return 0; 71 } 72 73 int main(void) { 74 #ifndef ONLINE_JUDGE 75 freopen("150.in", "r", stdin); 76 freopen("150.out", "w", stdout); 77 #endif 78 79 n = rd(), m = rd(); 80 F(i, 1, n-1) { 81 int x = rd(), y = rd(), d = rd(); 82 mp[++tot] = (E){y, d, hd[x]}, hd[x] = tot; 83 mp[++tot] = (E){x, d, hd[y]}, hd[y] = tot; 84 } 85 86 Son(1); 87 spl(1, 1); 88 89 F(i, 1, m) 90 u[i] = rd(), v[i] = rd(), anc[i] = LCA(u[i], v[i]); 91 92 int l = 0, r = 300000 * 1000; 93 while (l < r) { 94 int x = (l + r) >> 1; 95 Deq(x) ? r = x : l = x+1; 96 } 97 printf("%d\n", l); 98 99 return 0; 100 }

「NOIP 2015」運輸計劃