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