「NOIP 2015」运输计划
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「NOIP 2015」运输计划相关的知识,希望对你有一定的参考价值。
「题意」
给 $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」运输计划的主要内容,如果未能解决你的问题,请参考以下文章