• [cf566C]Logistical Questions


    记$d(x,y)$为$x$到$y$的距离,$cost_{x}=sum_{i=1}^{n}w_{i}d(x,i)^{frac{3}{2}}$为$x$的代价

    取$C$为足够大量,对于一条边权为$w$的边,在边上新建$wC-1$个点,这些点点权为0(即本身无影响),并将边拆成$wC$段,那么每一段边权为$frac{1}{C}$

    任取(新树中)一条路径${a_{1},a_{2},...,a_{l}}$,则$cost_{a_{i}}$具有凸性

    根据凸性定义,即求证$forall 2le jle l-1,2cost_{a_{j}}le cost_{a_{j-1}}+cost_{a_{j+1}}$

    代入其式子,不妨对每一个$i$都保证此性质,也即求证$2d(a_{j},i)^{frac{3}{2}}le d(a_{j-1},i)^{frac{3}{2}}+d(a_{j+1},i)^{frac{3}{2}}$

    对$i$的位置分类讨论:

    1.$i$距离$a_{j}$最近,则$d(a_{j},i)le d(a_{j-1},i),d(a_{j+1},i)$,显然成立

    2.$i$不距离$a_{j}$最近,记$x=d(a_{j},i)$,那么即$2x^{frac{3}{2}}le (x-frac{1}{C})^{frac{3}{2}}+(x+frac{1}{C})^{frac{3}{2}}$

    令$f(x)=x^{frac{3}{2}}$,代入并移项,也即$f(x)-f(x-frac{1}{C})le f(x+frac{1}{C})-f(x)$

    当$C$足够大时,两者可以看作$frac{f'(x)}{C}$和$frac{f'(x+frac{1}{C})}{C}$,注意到$f'(x)=frac{3}{2}x^{frac{1}{2}}$单调递增,即成立

    进而考虑其中非新建的点${b_{1},b_{2},...,b_{k}}$,根据$cost_{a_{i}}$的凸性,$cost_{b_{i}}$的形式必然是先严格单调递减、再有若干个相同的数(最小值)、最后严格单调递增(首尾两段允许为空)

    由于(原树中)任意一条路径都可以被以此法选择,即所有路径都为此形式


    (以下删去上述新建的点,即仍考虑原树)

    约定$x$为质心当且仅当$forall 1le ile n,cost_{x}le cost_{i}$,题目即要找到任意一个质心即可

    任取一点$x$,对与$x$相邻的点$y$,至多存在一个$y$满足$cost_{y}<cost_{x}$

    (否则任取其中两个记为$y_{1}$和$y_{2}$,考虑$y_{1}$到$y_{2}$的路径即矛盾)

    进一步的,再对其分类讨论:

    1.如果不存在$y$满足$cost_{y}<cost_{x}$,则对于树上任意一点$z$,考虑其到$x$的路径,由于最后一步仍没有递增,根据路径的形式不难得到$cost_{x}le cost_{z}$,也即$x$为质心

    2.如果存在$y$满足$cost_{y}<cost_{x}$,那么对于以$y$为根时$x$子树中的任意一点$z$,考虑其到$y$的路径,由于最后一步严格单调递减,根据路径的形式不难得到$cost_{y}<cost_{z}$,也即$z$一定不为质心

    综上,不难得到下述暴力做法——

    初始连通子树$T_{0}=T$,并任取$T_{0}$中一点$x$,求出所有与$x$相邻的点$y$的答案,若不存在$y$满足$cost_{y}<cost_{x}$则$x$为质心,若存在$y$满足$cost_{y}<cost_{x}$(必然唯一)令$T_{0}$为删去$x$后$y$所在的连通块并递归即可(第二种情况,剩下的部分一定不包含质心)

    如果令$x$为$T_{0}$中的重心(指通常的定义),那么每一次$T_{0}$的规模至少缩小一半,即至多$o(log n)$层

    但如果暴力计算所有$y$,仍会导致复杂度过高(每一次计算是$o(n)$的),考虑优化:

    对于所有边$(x,y,w)$,在边上新建一个点,其点权为0、到$x$距离为1、到$y$距离为$w-1$

    由此,只需要求出这些新建点的$cost$即可(注意其并不影响上述分析),维护(以$x$为根后)每一个新建点子树内所有点到其距离的$frac{3}{2}$次之和、到其距离+2的$frac{3}{2}$次之和即可

    (注意虽然重心一定在$T_{0}$中,但递归的仍是整个$T$)

    时间复杂度为$o(nlog n)$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 200005
     4 struct Edge{
     5     int nex,to,len;
     6 }edge[N<<1];
     7 int n,E,rt,x,y,z,a[N],head[N],sz[N],vis[N];
     8 void add(int x,int y,int z){
     9     edge[E]=Edge{head[x],y,z};
    10     head[x]=E++;
    11 }
    12 void get_sz(int k,int fa){
    13     sz[k]=1;
    14     for(int i=head[k];i!=-1;i=edge[i].nex)
    15         if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
    16             get_sz(edge[i].to,k);
    17             sz[k]+=sz[edge[i].to];
    18         }
    19 }
    20 void get_rt(int k,int fa,int s){
    21     int mx=s-sz[k];
    22     for(int i=head[k];i!=-1;i=edge[i].nex)
    23         if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
    24             get_rt(edge[i].to,k,s);
    25             mx=max(mx,sz[edge[i].to]);
    26         }
    27     if (mx<=(s>>1))rt=k;
    28 }
    29 double get_s(int k,int fa,int s){
    30     double sum=a[k]*(pow(s,1.5)-pow(s+2,1.5));
    31     for(int i=head[k];i!=-1;i=edge[i].nex)
    32         if (edge[i].to!=fa)sum+=get_s(edge[i].to,k,s+edge[i].len);
    33     return sum;
    34 }
    35 double get_cost(int k,int fa=0,int s=0){
    36     double sum=a[k]*pow(s,1.5);
    37     for(int i=head[k];i!=-1;i=edge[i].nex)
    38         if (edge[i].to!=fa)sum+=get_cost(edge[i].to,k,s+edge[i].len);
    39     return sum;
    40 }
    41 int dfs(int k){
    42     get_sz(k,0);
    43     get_rt(k,0,sz[k]);
    44     int pos=0;
    45     double s=1;
    46     for(int i=head[rt];i!=-1;i=edge[i].nex){
    47         double ss=get_s(edge[i].to,rt,edge[i].len-1);
    48         if (ss<s)pos=edge[i].to,s=ss;
    49     }
    50     if ((!pos)||(get_cost(rt)<=get_cost(pos)))return rt;
    51     vis[rt]=1;
    52     return dfs(pos);
    53 }
    54 int main(){
    55     scanf("%d",&n);
    56     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    57     memset(head,-1,sizeof(head));
    58     for(int i=1;i<n;i++){
    59         scanf("%d%d%d",&x,&y,&z);
    60         add(x,y,z),add(y,x,z);
    61         assert(z>=1);
    62     }
    63     x=dfs(1);
    64     printf("%d %.7f
    ",x,get_cost(x));
    65     return 0;
    66 }
    View Code
  • 相关阅读:
    如何在fragment里面嵌套viewpager?
    textview限制字数,结尾显示。。。。。
    限制imageview大小
    iOS开发核心动画之画图板
    iOS开发核心动画之九宫格解锁
    iOS开发核心动画之Quartz2D绘图
    iOS开发核心动画之触摸手指识别
    iOS开发网络多线程之断点下载
    iOS开发网络多线程之网络请求文件解析
    iOS开发网络多线程之Runloop无限循环
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15355472.html
Copyright © 2020-2023  润新知