[WC 2010]重建计划
Posted NaVi_Awson
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[WC 2010]重建计划相关的知识,希望对你有一定的参考价值。
Description
Input
第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai,Bi,Vi分别表示道路(Ai,Bi),其价值为Vi 其中城市由1..N进行标号
Output
输出最大平均估值,保留三位小数
Sample Input
4
2 3
1 2 1
1 3 2
1 4 3
2 3
1 2 1
1 3 2
1 4 3
Sample Output
2.500
HINT
N<=100000,1<=L<=U<=N-1,Vi<=1000000
题解
本机实测是可以 $A$ 的,但爆炸 $oj$ 的老爷机实在不可恭维,并且还多加了一组更为毒瘤的数据...
加了所有的常数优化都过不了,气愤的不想写题解,直接丢链接。
1 //It is made by Awson on 2018.1.5 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <cstdio> 9 #include <string> 10 #include <vector> 11 #include <cstdlib> 12 #include <cstring> 13 #include <iostream> 14 #include <algorithm> 15 #define LL long long 16 #define RE register 17 #define lowbit(x) ((x)&(-(x))) 18 #define Max(a, b) ((a) > (b) ? (a) : (b)) 19 #define Min(a, b) ((a) < (b) ? (a) : (b)) 20 using namespace std; 21 const int N = 100000; 22 const int INF = ~0u>>1; 23 const double eps = 4e-4; 24 void read(int &x) { 25 char ch; x = 0; 26 ch = getchar(); while (ch < \'0\' || ch > \'9\') ch = getchar(); 27 while (ch >= \'0\' && ch <= \'9\') x = (x<<1)+(x<<3)+ch-48, ch = getchar(); 28 } 29 30 int n, L, U, a, b, c; 31 struct tt { 32 int to, next; 33 double cost, c; 34 }edge[(N<<1)+5]; 35 int path[N+5], top; 36 int root[N+5]; 37 void add(int u, int v, double c) { 38 edge[++top].to = v; 39 edge[top].cost = edge[top].c = c; 40 edge[top].next = path[u]; 41 path[u] = top; 42 } 43 44 namespace PRE { 45 int size[N+5], mx[N+5], minsize, rt, vis[N+5], tot; 46 void get_root(int o, int pa, int fa) { 47 mx[o] = Max(mx[o], size[pa]-size[o]); 48 if (mx[o] < minsize) minsize = mx[o], rt = o; 49 for (RE int i = path[o]; i; i = edge[i].next) 50 if (edge[i].to != fa && !vis[edge[i].to]) get_root(edge[i].to, pa, o); 51 } 52 void get_size(int o, int fa) { 53 size[o] = 1, mx[o] = 0; 54 for (RE int i = path[o]; i; i = edge[i].next) 55 if (edge[i].to != fa && !vis[edge[i].to]) { 56 get_size(edge[i].to, o); 57 size[o] += size[edge[i].to]; 58 if (size[edge[i].to] > mx[o]) mx[o] = size[edge[i].to]; 59 } 60 } 61 void work(int o) { 62 minsize = INF; 63 get_size(o, 0), get_root(o, o, 0); 64 root[++tot] = rt, vis[rt] = 1; 65 for (RE int i = path[rt]; i; i = edge[i].next) 66 if (!vis[edge[i].to]) work(edge[i].to); 67 } 68 void main() {work(1); } 69 } 70 71 double mx[N+5], dist[N+5]; 72 int q[N+5], vis[N+5], dep[N+5], dq[N+5], fa[N+5]; 73 74 bool cal(int o) { 75 int maxdep = 0; 76 for (RE int I = path[o]; I; I = edge[I].next) 77 if (!vis[edge[I].to]) { 78 int head = 0, tail = 0; q[tail] = edge[I].to, dep[q[0]] = 1, dist[q[0]] = edge[I].cost, fa[q[0]] = o, ++tail; 79 while (head < tail) { 80 int now = q[head]; ++head; 81 for (RE int i = path[now]; i; i = edge[i].next) 82 if (fa[now] != edge[i].to && !vis[edge[i].to]) { 83 q[tail] = edge[i].to, ++tail; 84 dep[edge[i].to] = dep[now]+1; 85 dist[edge[i].to] = dist[now]+edge[i].cost; 86 fa[edge[i].to] = now; 87 } 88 } 89 int head1 = 0, tail1 = 0, now = maxdep; 90 for (RE int i = 0; i < tail; ++i) { 91 int x = q[i]; 92 while (dep[x]+now >= L && now >= 0) { 93 while (head1 < tail1 && mx[dq[tail1-1]] < mx[now]) --tail1; 94 dq[tail1] = now; ++tail1, --now; 95 } 96 while (head1 < tail1 && dq[head1]+dep[x] > U) ++head1; 97 if (head1 < tail1 && dist[x]+mx[dq[head1]] >= 0) return true; 98 } 99 maxdep = Max(maxdep, dep[q[tail-1]]); 100 for (RE int i = 0; i < tail; ++i) { 101 fa[q[i]] = 0; if (mx[dep[q[i]]] < dist[q[i]]) mx[dep[q[i]]] = dist[q[i]]; 102 } 103 } 104 for (RE int i = 1; i <= maxdep; i++) mx[i] = -INF; 105 return false; 106 } 107 bool solve(int o, int &num) { 108 vis[o] = 1; 109 if (cal(o)) return true; 110 for (RE int i = path[o]; i ;i = edge[i].next) 111 if (!vis[edge[i].to]) { 112 ++num; if (solve(root[num], num)) return true; 113 } 114 return false; 115 } 116 void pre(double key) { 117 for (RE int i = 1; i <= n; ++i) { 118 edge[i<<1].cost = edge[i<<1].c-key, edge[(i<<1)-1].cost = edge[(i<<1)-1].c-key; 119 vis[i] = 0, mx[i] = -INF; 120 } 121 } 122 void work() { 123 read(n), read(L), read(U); 124 double L = 0, R = 0; 125 for (RE int i = 1; i < n; ++i) { 126 read(a), read(b), read(c); 127 add(a, b, c), add(b, a, c); if (R < c) R = c; 128 } 129 PRE::main(); 130 while (R-L > eps) { 131 double mid = (L+R)/2.; pre(mid); 132 int tot = 1; 133 if (solve(root[1], tot)) L = mid; 134 else R = mid; 135 } 136 printf("%.3lf\\n", (L+R)/2.); 137 } 138 int main() { 139 work(); 140 return 0; 141 }
以上是关于[WC 2010]重建计划的主要内容,如果未能解决你的问题,请参考以下文章