• [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

    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 }
  • 相关阅读:
    查看MySQL数据库表的命令介绍
    MySQL 数据库常用命令 超级实用版分享
    从cmd中进入MySQL的命令界面
    POJ-1664 放苹果
    ant常用命令
    ant来历
    ant
    ant有什么用
    ANT的安装和配置(windows)
    Experimental Educational Round: VolBIT Formulas Blitz B
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8214975.html
Copyright © 2020-2023  润新知