码迷,mamicode.com
首页 > 其他好文 > 详细

[Wc2010]重建计划

时间:2018-01-06 20:02:41      阅读:219      评论:0      收藏:0      [点我收藏+]

标签:esc   接下来   重建   font   上下限   scanf   nav   double   blog   

 

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 

题解在这里

ZYYS

 

  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 }

 

[Wc2010]重建计划

标签:esc   接下来   重建   font   上下限   scanf   nav   double   blog   

原文地址:https://www.cnblogs.com/Y-E-T-I/p/8214975.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!