zoukankan      html  css  js  c++  java
  • bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check

    [Wc2010]重建计划

    Time Limit: 40 Sec  Memory Limit: 162 MB
    Submit: 4345  Solved: 1054
    [Submit][Status][Discuss]

    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 新加数据一组 By leoly,但未重测..2016.9.27

    题解:点分上是一个log,二分是一个log,然后是单调队列判断,n,总复杂度O(nlogn^2)

    hzwer的代码十分不优秀,应该是按照最低深度从小到大去个棵子树去判断才可以,不然是不行的,

    不然会是复杂度退化成n^2

    改了比较siz还是T,不知道为什么了。

      1 #include<cstring>
      2 #include<cmath>
      3 #include<iostream>
      4 #include<algorithm>
      5 #include<cstdio>
      6 #include<cstdlib>
      7 #include<vector>
      8 
      9 #define inf 1000000007
     10 #define eps 0.0001
     11 #define N 100007
     12 #define M 200007
     13 #define ll long long
     14 using namespace std;
     15 inline int read()
     16 {
     17     int x=0,f=1;char ch=getchar();
     18     while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
     19     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
     20     return x*f;
     21 }
     22 
     23 int n,S,L,U,rt,lim;
     24 double ans;
     25 int cnt,hed[N],rea[M],val[M],nxt[M];
     26 int sz[N],fa[N],f[N],dep[N];
     27 int q[N],dq[N];
     28 bool flag[N];
     29 double dis[N],mx[N];
     30 int num[N*10],xz,shu[N*10];
     31 
     32 void add(int u,int v,int w)
     33 {
     34     nxt[++cnt]=hed[u];
     35     hed[u]=cnt;
     36     rea[cnt]=v;
     37     val[cnt]=w;
     38 }
     39 void get_root(int u,int fa)
     40 {
     41     sz[u]=1,f[u]=0;
     42     for (int i=hed[u];i!=-1;i=nxt[i])
     43     {
     44         int v=rea[i];
     45         if (v==fa||flag[v]) continue;
     46         get_root(v,u);
     47         sz[u]+=sz[v];
     48         f[u]=max(f[u],sz[v]);
     49     }
     50     f[u]=max(f[u],S-sz[u]);
     51     if (f[u]<=f[rt])rt=u;
     52 }
     53 bool check(int rt,double zhi)
     54 {
     55     int up=0;
     56     for (int i=hed[rt];i!=-1;i=nxt[i])
     57     {
     58         int v=rea[i];double fee=(double)val[i]-zhi;
     59         if (flag[v])continue;
     60         int hd=0,tl=1;
     61         q[0]=v;
     62         fa[v]=rt,dep[v]=1;
     63         dis[v]=fee;
     64         while(hd!=tl)
     65         {
     66             int now=q[hd];hd++;
     67             for (int i=hed[now];i!=-1;i=nxt[i])
     68             {
     69                 int v=rea[i];double fee=(double)val[i]-zhi;
     70                 if (v==fa[now]||flag[v])continue;
     71                 q[tl++]=v;
     72                 fa[v]=now,dep[v]=dep[now]+1;
     73                 dis[v]=dis[now]+fee;
     74             }
     75         }
     76         int l=1,r=0,now=up;
     77         for (int i=0;i<tl;i++)
     78         {
     79             int x=q[i];
     80             while(dep[x]+now>=L&&now>=0)
     81             {
     82                 while(l<=r&&mx[dq[r]]<mx[now])r--;
     83                 dq[++r]=now;
     84                 now--;
     85             }
     86             while(l<=r&&dep[x]+dq[l]>U)l++;
     87             if (l<=r&&dis[x]+mx[dq[l]]>=0)return 1;
     88         }
     89         for (int i=up+1;i<=dep[q[tl-1]];i++)mx[i]=-inf;
     90         for (int i=0;i<tl;i++)
     91         {
     92             int x=q[i];
     93             mx[dep[x]]=max(mx[dep[x]],dis[x]);
     94         }
     95         up=max(up,dep[q[tl-1]]);
     96     }
     97     return 0;
     98 }
     99 void cal(int u)//可以
    100 {
    101     double l=ans,r=lim,mid;
    102     while(r-l>eps)
    103     {
    104         mid=(l+r)/2;
    105         if(check(u,mid))l=mid;
    106         else r=mid;
    107     }
    108     ans=l;    
    109 }
    110 bool cmp(int x,int y)
    111 {
    112     return shu[x]<shu[y];
    113 }
    114 void solve(int u)
    115 {
    116     cal(u);
    117     flag[u]=1;int yl=xz,Sum=S;
    118     for (int i=hed[u];i!=-1;i=nxt[i])
    119     {
    120         int v=rea[i];
    121         if (flag[v])continue;
    122         rt=0;
    123         if (sz[v]<sz[u])S=sz[v];
    124         else S=Sum-sz[u];
    125         get_root(v,0);
    126         if(sz[v]>L)num[++xz]=rt,shu[++xz]=S;
    127     }
    128     sort(num+yl+1,num+xz+1,cmp);
    129     for (int i=yl+1;i<=xz;i++)
    130         solve(num[i]);
    131     xz=yl;
    132 }
    133 int main()
    134 {
    135     memset(hed,-1,sizeof(hed));
    136     n=read(),L=read(),U=read();
    137     for (int i=1;i<n;i++)
    138     {
    139         int u=read(),v=read(),w=read();
    140         add(u,v,w),add(v,u,w);
    141         lim=max(lim,w);
    142     }
    143     f[0]=n;
    144     rt=0,S=n;
    145     get_root(1,0);
    146     solve(rt);
    147     printf("%.3lf",ans);
    148 }
  • 相关阅读:
    《Mysql
    《Redis
    《pt-query-digest 剖析 Mysql 慢日志》
    《Redis
    《Redis
    《Redis
    《Redis
    《Redis
    python中__new__()与__init__()的区别
    Python常见综合面试题
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8250990.html
Copyright © 2011-2022 走看看