[Wc2010]重建计划
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
题解在这里
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 struct Node 7 { 8 int next,to; 9 double d,c; 10 }edge[200001]; 11 int num,head[100001],size[100001],maxsize[100001],minsize,root; 12 int rt[100001],tot,n,fa[100001],L,U,dep[100001]; 13 double mx[100001],dist[100001]; 14 bool vis[100001]; 15 void add(int u,int v,double d) 16 { 17 num++; 18 edge[num].next=head[u]; 19 head[u]=num; 20 edge[num].to=v; 21 edge[num].d=d; 22 } 23 void get_size(int x,int pa) 24 {int i; 25 size[x]=1;maxsize[x]=0; 26 for (i=head[x];i;i=edge[i].next) 27 { 28 int v=edge[i].to; 29 if (v==pa||vis[v]) continue; 30 get_size(v,x); 31 size[x]+=size[v]; 32 if (size[v]>maxsize[x]) maxsize[x]=size[v]; 33 } 34 } 35 void get_root(int x,int pa,int r) 36 {int i; 37 maxsize[x]=max(maxsize[x],size[r]-size[x]); 38 if (maxsize[x]<minsize) 39 { 40 minsize=maxsize[x]; 41 root=x; 42 } 43 for (i=head[x];i;i=edge[i].next) 44 { 45 int v=edge[i].to; 46 if (v==pa||vis[v]) continue; 47 get_root(v,x,r); 48 } 49 } 50 void pre_divide(int x) 51 {int i; 52 minsize=2e9; 53 get_size(x,0); 54 get_root(x,0,x); 55 rt[++tot]=root; 56 vis[root]=1; 57 for (i=head[root];i;i=edge[i].next) 58 { 59 int v=edge[i].to; 60 if (vis[v]==0) 61 pre_divide(v); 62 } 63 } 64 void pre(double x) 65 {int i; 66 for (i=1;i<=n;i++) 67 { 68 edge[i*2-1].c=edge[i*2-1].d-x; 69 edge[i*2].c=edge[i*2].d-x; 70 vis[i]=0;mx[i]=-2e9; 71 } 72 } 73 bool pd(int root) 74 {int i; 75 int maxdep=0; 76 int q[100001],h=0,t=0,I,Q[100001]; 77 for (I=head[root];I;I=edge[I].next) 78 { 79 int v=edge[I].to; 80 if (vis[v]) continue; 81 h=0;t=1; 82 fa[v]=root;dist[v]=edge[I].c; 83 dep[v]=1; 84 q[1]=v; 85 while (h<t) 86 { 87 h++; 88 int u=q[h]; 89 if (dep[u]==U) break; 90 for (i=head[u];i;i=edge[i].next) 91 { 92 int v=edge[i].to; 93 if (fa[u]!=v&&vis[v]==0) 94 { 95 fa[v]=u; 96 dep[v]=dep[u]+1; 97 dist[v]=dist[u]+edge[i].c; 98 t++; 99 q[t]=v; 100 } 101 } 102 } 103 int hh=0,tt=0,now=maxdep; 104 for (i=1;i<=t;i++) 105 { 106 int x=q[i]; 107 while (dep[x]+now>=L&&now>=0) 108 { 109 while (hh<tt&&mx[Q[tt]]<mx[now]) tt--; 110 tt++;Q[tt]=now;now--; 111 } 112 while (hh<tt&&Q[hh+1]+dep[x]>U) hh++; 113 if (hh<tt&&mx[Q[hh+1]]+dist[x]>=0) return 1; 114 } 115 maxdep=max(maxdep,dep[q[t]]); 116 for (i=1;i<=t;i++) 117 { 118 fa[q[i]]=0; 119 if (dist[q[i]]>mx[dep[q[i]]]) mx[dep[q[i]]]=dist[q[i]]; 120 } 121 } 122 for (i=0;i<=maxdep;i++) 123 mx[i]=-2e9; 124 return 0; 125 } 126 bool check(int root,int &num) 127 {int i; 128 vis[root]=1; 129 if (pd(root)) return 1; 130 for (i=head[root];i;i=edge[i].next) 131 { 132 int v=edge[i].to; 133 if (vis[v]==0) 134 { 135 num++; 136 if (check(rt[num],num)) return 1; 137 } 138 } 139 return 0; 140 } 141 int main() 142 {int i,u,v; 143 double d,r,eps=1e-4; 144 cin>>n; 145 cin>>L>>U; 146 for (i=1;i<=n-1;i++) 147 { 148 scanf("%d%d%lf",&u,&v,&d); 149 add(u,v,d);add(v,u,d); 150 r=max(r,d); 151 } 152 pre_divide(1); 153 double l=0; 154 while (r-l>eps) 155 { 156 double mid=(l+r)/2.0; 157 pre(mid); 158 int tot=1; 159 if (check(rt[1],tot)) l=mid; 160 else r=mid; 161 } 162 printf("%.3lf",(l+r)/2.0); 163 }