zoukankan      html  css  js  c++  java
  • [COGS2652]秘术「天文密葬法」

    description

    题面
    给个树,第(i)个点有两个权值(a_i)(b_i),现在求一条长度为(m)的路径,使得(frac{sum a_i}{sum b_i})最小

    data range

    [mle nle 2 imes 10^5 ]

    solution

    0/1分数规划?二分吧。
    二分一个值(S),要使得(frac{sum a_i}{sum b_i}le S)
    那么$$sum(a_i-Sb_i)le0$$
    把每个点的点权做成这个,然后(DP check)最优答案是否(le 0)就行

    如何(DP)?
    暴力的,(f_{i,j})表示(i)子数内长度为(j)的链的最优解,转移是(O(n^2))

    按照深度的树上(DP)可以使用长链剖分优化到(O(n))

    总复杂度就是(O(nlogsum w))

    code

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<complex>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<ctime>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define FILE "cdcq_b"
    #define mp make_pair
    #define pb push_back
    #define RG register
    #define il inline
    using namespace std;
    typedef unsigned long long ull;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    const dd eps=1e-4;
    const int mod=998244353;
    const int N=200010;
    const dd pi=acos(-1);
    const int inf=2147483647;
    const ll INF=1e18+1;
    const ll P=100000;
    il ll read(){
    	RG ll data=0,w=1;RG char ch=getchar();
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
    	return data*w;
    }
    
    il void file(){
    	srand(time(NULL)+rand());
    	freopen(FILE".in","r",stdin);
    	freopen(FILE".out","w",stdout);
    }
    
    int n,m;dd x[N],y[N];
    int head[N],nxt[N<<1],to[N<<1],cnt;
    int len[N],son[N];
    void dfs1(int u,int fa){
    	for(RG int i=head[u];i;i=nxt[i]){
    		RG int v=to[i];if(v==fa)continue;
    		dfs1(v,u);if(len[son[u]]<len[v])son[u]=v;
    	}
    	len[u]=len[son[u]]+1;
    }
    
    dd *pos,f[N],*A[N],tag[N],ans,K;
    void dfs2(int u,int fa){
    	pos++;A[u]=pos;dd *a=A[u];
    	if(!son[u]){
    		a[0]=x[u]*1.0-K*y[u];
    		if(m==1)ans=min(ans,a[0]);
    		return;
    	}
    	dfs2(son[u],u);
    
    	tag[u]=tag[son[u]]+x[u]*1.0-K*y[u];
    	a[0]=x[u]*1.0-K*y[u]-tag[u];
    	dd *b;
    	for(RG int i=head[u];i;i=nxt[i]){
    		RG int v=to[i];if(v==fa||v==son[u])continue;
    		dfs2(v,u);b=A[v];
    		if(m==1)ans=min(ans,b[0]+tag[v]);
    		else 
    			for(RG int j=0;j<m-1&&j<len[v];j++)
    				if(m-j-2<len[u])ans=min(ans,b[j]+tag[v]+a[m-j-2]+tag[u]);		
    		for(RG int j=0;j<len[v];j++)
    			a[j+1]=min(a[j+1],b[j]+tag[v]+x[u]*1.0-K*y[u]-tag[u]);
    	}
    	if(len[u]>=m)ans=min(ans,a[m-1]+tag[u]);
    }
    
    dd g[N];
    void dfs3(int u,int fa){
    	if(!son[u]){g[u]=x[u]*1.0-K*y[u];ans=min(ans,g[u]);return;}
    	dfs3(son[u],u);if(g[son[u]]<0)g[u]+=g[son[u]];else g[u]=0;
    	for(RG int i=head[u];i;i=nxt[i]){
    		RG int v=to[i];if(v==fa||v==son[u])continue;
    		dfs3(v,u);ans=min(ans,g[u]+x[u]*1.0-K*y[u]+g[v]);
    		g[u]=min(g[u],g[v]);
    	}
    	g[u]+=x[u]*1.0-K*y[u];ans=min(ans,g[u]);
    }
    
    il bool check(){
    	ans=INF;
    	if(m!=-1){pos=f;memset(f,0,sizeof(f));dfs2(1,0);}
    	else dfs3(1,0);
    	return ans<eps;
    }
    
    int main()
    {
    	file();
    	RG dd l=0,r=0,mid,as=-INF;
    	scanf("%d%d",&n,&m);
    	if(n==1||(m!=-1&&m>=n)){puts("-1");return 0;}
    	for(RG int i=1;i<=n;i++){scanf("%lf",&x[i]);r+=x[i];}
    	for(RG int i=1;i<=n;i++){
    		scanf("%lf",&y[i]);
    	}
    	for(RG int i=1,u,v;i<n;i++){
    		u=read();v=read();
    		to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
    		to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt;
    	}
    	dfs1(1,0);
    	
    	while(r-l>=eps){
    		K=mid=(l+r)/2;
    		if(!check())l=mid;
    		else as=mid,r=mid;
    	}
    	
    	if(as==-INF)puts("-1");
    	else printf("%.2lf
    ",as);
    	return 0;
    }
    
    
  • 相关阅读:
    闭包
    关于this
    插件开发(对象级)
    IFC
    flex.css
    js移动端滑动事件
    Android 手机下输入框获取焦点时, 输入法挡住输入框的 bug
    vue 组件化spreadjs预览excel
    feign 熔断工厂 fallbackFactory的简单实现
    bat脚本批量启动程序
  • 原文地址:https://www.cnblogs.com/cjfdf/p/9483714.html
Copyright © 2011-2022 走看看