[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

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]重建计划的主要内容,如果未能解决你的问题,请参考以下文章

[WC2010]重建计划(分数规划+点分治+单调队列)

bzoj1758 [Wc2010]重建计划

bzoj1758[Wc2010]重建计划

bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check

Luogu4292 WC2010重建计划

WC2010重建计划