比赛 |
cdcqの省选膜你赛 |
评测结果 |
WWAAAWWWWWAWAAWAAAAA |
题目名称 |
秘术「天文密葬法」 |
最终得分 |
55 |
用户昵称 |
loveccc |
运行时间 |
1.259 s |
代码语言 |
C++ |
内存使用 |
11.92 MiB |
提交时间 |
2017-04-11 21:39:06 |
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<algorithm>
const int len=2e5+10;
const double eps=1e-5;
const long double inf=(long long)len*len;
struct node{
int next,b;
} e[len*2];
int n,hash[len],tot,f[len],sz[len],sum,m,root;
int x,y;
double ans,t[len],w[len],ans1,a[len],b[len];
bool vis[len];
void read(int &x){
x=0;int f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
x*=f;
}
void add(int x,int y){
e[++tot].b=y;e[tot].next=hash[x];hash[x]=tot;
}
void getroot(int x,int fa){
sz[x]=f[x]=1;
for (int i=hash[x];i;i=e[i].next)
if (e[i].b!=fa&&!vis[e[i].b]){
getroot(e[i].b,x);
sz[x]+=sz[e[i].b];
f[x]=std::max(f[x],sz[e[i].b]);
}
f[x]=std::max(sum-sz[x],f[x]);
if (f[x]<f[root])root=x;
}
void getdeep(int x,int fa,int c,double wi){
if (c>m)return;
if (t[m-c]+wi<ans1&&t[m-c]!=inf)ans1=t[m-c]+wi;
for (int i=hash[x];i;i=e[i].next)
if (e[i].b!=fa&&!vis[e[i].b]){
getdeep(e[i].b,x,c+1,wi+w[e[i].b]);
}
}
void updata(int x,int fa,int c,double wi){
if (c>m)return;
if (wi<t[c])t[c]=wi;
for (int i=hash[x];i;i=e[i].next)
if (e[i].b!=fa&&!vis[e[i].b]){
updata(e[i].b,x,c+1,wi+w[e[i].b]);
}
}
void del(int x,int fa,int c){
if (c>m)return;
t[c]=inf;
for (int i=hash[x];i;i=e[i].next)
if (e[i].b!=fa&&!vis[e[i].b]){
del(e[i].b,x,c+1);
}
}
void cal(int x){
for (int i=hash[x];i;i=e[i].next)
if (!vis[e[i].b]){
getdeep(e[i].b,x,2,w[e[i].b]+w[x]);
updata(e[i].b,x,1,w[e[i].b]);
}
del(x,0,1);
}
void work(int x){
vis[x]=1; cal(x);
for (int i=hash[x];i;i=e[i].next)
if (!vis[e[i].b]){
sum=f[0]=sz[e[i].b];root=0;
work(root);
}
}
bool check(double x){
for (int i=1;i<=n;i++) w[i]=(double)a[i]-x*b[i],vis[i]=0;
for (int i=1;i<=m;i++) t[i]=inf;
f[0]=sum=n;root=0; ans1=inf;
getroot(1,0);
work(root);
if (ans1-eps>=0&&ans1!=inf)return true;
return false;
}
void try1(){
double l=0,r=n*len;
while (r-l>=eps){
double mid=(l+r)/2;
if (check(mid)) ans=mid,l=mid+eps;
else r=mid-eps;
}
printf("%.2f\n",ans);
}
void try2(){
ans=inf;
for (int i=1;i<=n;i++)
if (a[i]/b[i]<ans)ans=a[i]/b[i];
printf("%.2f\n",ans);
}
int main(){
freopen("cdcq_b.in","r",stdin); freopen("cdcq_b.out","w",stdout);
read(n);read(m);
for (int i=1;i<=n;i++)read(x),a[i]=x;
for (int i=1;i<=n;i++)read(x),b[i]=x;
for (int i=2;i<=n;i++){
read(x);read(y); add(x,y); add(y,x);
}
if(m!=-1)try1();
else try2();
}