• CF348B Solution


    题解

    因为一棵树的权值被根节点各子节点的子树平分,因此可以求出叶子节点(i)的权值对根节点的贡献,设其为(frac{1}{va_i})。也就是说,对于节点(i)(1)权值的比重是(frac{1}{va_i cdot a_i}),而目标就是将这些叶子节点单位权值的比重统一,并使其最小。因为随着(a_i)减小,(frac{1}{va_i cdot a_i})增大,所以最终的单位权值比重不会小于(frac{1}{va_i cdot a_i})的最大值,且可以被所有(va_i)整除(使其他叶子节点能够变化过来)。求出(lcm(a_i)_{i=1}^n)小于等于(min(va_icdot a_i)_{i=1}^n)的最大倍数,也就是剩余的节点权值和,用初始权值和减去它即为答案。

    代码

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=1e5+10,inf=0x3f3f3f3f3f3f3f3f;
    int fst[N],nxt[2*N],v[2*N],cnt;
    int a[N],va[N],mi=inf,lcm=1,sum;
    inline int read()
    {
    	int s=0,w=1; char ch=getchar();
    	while(ch<'0' || ch>'9') {if(ch=='-') w=-1; ch=getchar();}
    	while(ch>='0' && ch<='9') s=s*10+ch-'0',ch=getchar();
    	return s*w;
    }
    void add(int x,int y)
    {
    	v[++cnt]=y;
    	nxt[cnt]=fst[x],fst[x]=cnt;
    }
    int gcd(int x,int y) {return (!y)?x:gcd(y,x%y);}
    void dfs(int x,int fa)
    {
    	lcm=lcm*va[x]/gcd(lcm,va[x]);
    	if(va[x]>sum || va[x]<0) {printf("%lld",sum); exit(0);}
    	int tmp=0,y;
    	for(int i=fst[x];i;i=nxt[i])
    		if(v[i]!=fa) tmp++;
    	if(!tmp) mi=min(mi,va[x]*a[x]);
    	for(int i=fst[x];i;i=nxt[i])
    	{
    		y=v[i];
    		if(y==fa) continue;
    		va[y]=va[x]*tmp; dfs(y,x);
    	}
    }
    signed main()
    {
    	int n=read(),x,y;
    	for(int i=1;i<=n;i++) a[i]=read(),sum+=a[i];
    	for(int i=1;i<n;i++) 
    	{
    		x=read(),y=read();
    		add(x,y),add(y,x);
    	}
    	va[1]=1; dfs(1,0);
    	printf("%lld",sum-mi/lcm*lcm);
    	return 0;
    }
    
  • 相关阅读:
    Mysql查询数据库表结构以及字段类型并展示
    Configutation读取properties文件信息
    通过淘宝接口免费获取IP地址信息
    SpringMVC+SPring+Maven+Mybaits+Shiro+Mybaits基础开发项目
    【微信开发】【Asp.net MVC】-- 微信分享功能
    NPOI导出多张图片到Excel
    年末回想 ---- 小步快跑
    【吉光片羽】短信验证
    【JavaScript吉光片羽】--- 滑动条
    电子书和纸质书有什么区别
  • 原文地址:https://www.cnblogs.com/violetholmes/p/15330439.html
Copyright © 2020-2023  润新知