kZjPBD.jpg

【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\n",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\n",l);
88     return 0;
89 }

 

posted @ 2019-06-20 15:44  Through_The_Night  阅读(735)  评论(0编辑  收藏  举报