比赛 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();
}