zoukankan      html  css  js  c++  java
  • 【COGS2652】秘术「天文密葬法」(长链剖分,分数规划)

    永琳需要协助紫解决异变!

    在某个满月的夜晚,幻想乡的结界出现了异常,虽然目前还没有找到原因,不过有一点可以肯定的是,这次异变一定和满月有关。间隙妖怪紫在试图修复结界时需要永琳帮她排除满月产生的干扰,为了保护辉夜公主,永琳必须协助紫解决这次异变,所以她打算再次使用符卡"秘术「天文密葬法」"来用虚假的月亮替换真实的满月,但是她在使用符卡的时候出现了一些问题。

    "秘术「天文密葬法」"由n个使魔组成,每个使魔都有一个能值和一个波值,同时存在n-1条能量通道将这n个使魔连接起来,并且每个使魔都能通过能量通道和其它所有使魔相连。

    完成天文密葬法的关键步骤是在这n个使魔中找到一条用能量通道连接起来的路径,将大部分能量集中于这条路径来展开法术,然而路径上的使魔在法术张开时会产生共振,产生一个干扰值,干扰值等于路径上所有使魔能值的和除以波值的和。

    为了确保计划顺利进行,永琳需要选择一条长度为m且干扰值最小的路径,虽然作为月之头脑,但此时永琳需要集中精力展开法术,所以她向你求助。

    永琳在知道一个干扰值后就能快速找到这个干扰值对应的路径,你只需要告诉她所有路径中干扰值最小的路径干扰值是多少

    答案四舍五入到小数点后两位

    一句话题意:

    给个树,第i个点有两个权值ai和bi,现在求一条长度为m的路径,使得Σai/Σbi最小


    【输入格式】


    第一行一个整数n,m,意义如上

    如果m为-1则表示对长度没有限制(但路径不能为空

    第二行n个整数,第i个整数ai表示第i个使魔的能值

    第三行n个整数,第i个整数bi表示第i个使魔的波值

    接下来n-1行,每行两个整数l,r,表示有一条能量路径连接第l个使魔和第r个使魔

    一行中的所有整数均用空格隔开


    【输出格式】


    如果不存在长度为m的链,请输出-1

    否则一行一个浮点数,表示干扰值最小的路径干扰值是多少


    【样例输入1】


    3 2

    2 3 3

    6 6 6

    1 2

    2 3


    【样例输出1】

    0.42

    【样例输入2】


    9 3

    9 4 4 1 6 5 1 9 5

    8 3 3 1 5 4 1 8 4

    1 2

    2 3

    3 4

    3 5

    1 6

    6 7

    7 8

    6 9


    【样例输出2】

    1.15

    【数据范围】

     

    数据标号 n m ai,bi
    1 <=10 =1 <=200000
    2
    3 <=1000 <=n
    4
    5
    6
    7 <=30000
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17 <=200000 =-1
    18

    19

    20







    看到这个式子就是裸的分数规划吧。。。
    二分一个答案k,式子变成了找一条长度为m的路径(题目里面路径长度的定义是点数)
    满足∑a−k∑b≤0。
    首先直接把m=−1也就是没有限制的点直接判掉,这个东西没有任何意义。
    (其实m=1的和没有限制是一样的。。。。)
    现在把每个点的点权化为Vi=ai−kbi,要找出一条长度为m的路径使得点权和最小。
    然后就是怎么找长度为m的路径

     设 f i ,j 为以i为根节点的子树,距离根节点距离为j的权值和的最小值,然后n方的dp就很好打了

    考虑长链剖分优化,很明显,对于一个点的子树中,我们只需要维护在相同深度中,距离它的点权和最小的那个点的点权和,距离当前根节点这个东西很不好转移,直接变成距离整棵树的根节点的距离,这样子直接减一下就好了。
    那么链就只有两种情况了,一种是在一个LCA的地方转一下,这个在暴力更新轻儿子贡献的时候直接算一下。另一种是根节点向下延伸了m,这个在更新完了只有直接check一下就好了。

    orz yyb







     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<algorithm>
     7 using namespace std;
     8 #define ll long long
     9 #define MAX 200200
    10 inline int read()
    11 {
    12     int x=0;bool t=false;char ch=getchar();
    13     while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    14     if(ch=='-')t=true,ch=getchar();
    15     while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    16     return t?-x:x;
    17 }
    18 struct Line{int v,next;}e[MAX<<1];
    19 int h[MAX],cnt=1;
    20 inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
    21 double ans=1e18,V[MAX];
    22 int a[MAX],b[MAX];
    23 int n,m,md[MAX],dep[MAX],hson[MAX],len[MAX];
    24 void dfs1(int u,int ff)
    25 {
    26     md[u]=dep[u]=dep[ff]+1;
    27     for(int i=h[u];i;i=e[i].next)
    28     {
    29         int v=e[i].v;if(v==ff)continue;
    30         dfs1(v,u);
    31         if(md[v]>md[hson[u]])hson[u]=v;
    32     }
    33     if(hson[u])md[u]=md[hson[u]];len[u]=md[u]-dep[u]+1;
    34 }
    35 double tmp[MAX],*f[MAX],*id=tmp;
    36 void dfs2(int u,int ff)
    37 {
    38     if(hson[u])f[hson[u]]=f[u]+1,dfs2(hson[u],u);
    39     for(int i=h[u];i;i=e[i].next)
    40     {
    41         int v=e[i].v;if(v==ff||v==hson[u])continue;
    42         f[v]=id;id+=len[v];dfs2(v,u);
    43     }
    44 }
    45 void dfs(int u,int ff)
    46 {
    47     V[u]+=V[ff];f[u][0]=V[u];
    48     if(hson[u])dfs(hson[u],u);
    49     for(int i=h[u];i;i=e[i].next)
    50     {
    51         int v=e[i].v;if(v==ff||v==hson[u])continue;
    52         dfs(v,u);
    53         for(int j=0;j<len[v];++j)
    54             if(len[u]>m-j-1&&m-j-1>=0)ans=min(ans,f[u][m-j-1]+f[v][j]-V[u]-V[ff]);
    55         for(int j=0;j<len[v];++j)
    56             f[u][j+1]=min(f[u][j+1],f[v][j]);
    57     }
    58     if(len[u]>m)ans=min(ans,f[u][m]-V[ff]);
    59 }
    60 int main()
    61 {
    62     freopen("cdcq_b.in","r",stdin);
    63     freopen("cdcq_b.out","w",stdout);
    64     n=read();m=read();
    65     for(int i=1;i<=n;++i)a[i]=read();
    66     for(int i=1;i<=n;++i)b[i]=read();
    67     for(int i=1;i<n;++i)
    68     {
    69         int u=read(),v=read();
    70         Add(u,v);Add(v,u);
    71     }
    72     if(m==-1)
    73     {
    74         for(int i=1;i<=n;++i)ans=min(ans,1.0*a[i]/b[i]);
    75         printf("%.2lf
    ",ans);
    76         return 0;
    77     }
    78     dfs1(1,0);f[1]=id;id+=md[1];dfs2(1,1);
    79     double l=0,r=1e9;m-=1;
    80     while(r-l>=1e-5)
    81     {
    82         double mid=(l+r)/2;ans=1e18;
    83         for(int i=1;i<=n;++i)V[i]=a[i]-mid*b[i],tmp[i]=1e18;
    84         dfs(1,0);
    85         if(ans<=0)r=mid;else l=mid;
    86     }
    87     if(l>=5e8)puts("-1");else printf("%.2lf
    ",l);
    88     return 0;
    89 }
  • 相关阅读:
    递归和迭代
    The Rose
    读周国平作品有感
    matlab最小二乘法数据拟合函数详解
    读周国平作品有感
    three.js之创建一条直线
    three.js之创建一个几何体
    Go语言标准库之strconv
    Go语言基础之网络编程
    Go语言基础之并发
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11059140.html
Copyright © 2011-2022 走看看