jzoj3519

版权声明:本博客為本人嘔心瀝血之作,未經允許禁止轉載! https://blog.csdn.net/qq_39529862/article/details/85215441

我們考慮將一個節點x的所有兒子的數都改成y
記lcm[x]表示一個點的所有子節點的lcm值
那麼我們會發現y*deg[x] 要被lcm[x]整除
那麼x就會比x所有子節點最小的數小,記為z
那麼x就是比z小的數中,可以整除lcm[x]/deg[x]的最大的數
會不會導致x不能整除它對應的lcm?不會
因為lcm[x]/deg[x]就是它所有子節點的lcm,可以整除x的所有子節點

#include<bits/stdc++.h>
using namespace std;
long long lcs[100010],ans,a[100010],vis[100010],n;
long long lcm(long long a,long long b){return a*b/__gcd(a,b);}
vector<int>v[100010];
void dfs(int x){
	vis[x]=1;
	if(a[x]!=0){
		lcs[x]=1;
		return;
	}
	long long sc=0,minn=1e15,sum=0;
	lcs[x]=1;
	for(int i=0;i<(int)v[x].size();i++)
		if(vis[v[x][i]]==0){
			dfs(v[x][i]);
			sum+=a[v[x][i]];
			sc++;
			minn=min(minn,a[v[x][i]]);
			lcs[x]=lcm(lcs[x],lcs[v[x][i]]);
		}
	lcs[x]*=sc;
	long long m=minn-(minn%(lcs[x]/sc));
	ans+=sum-m*sc;
	a[x]=m*sc;
}
int main(){
	freopen("pylon.in","r",stdin);
	freopen("pylon.out","w",stdout);
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	for(int i=1;i<n;i++){
		int x,y;
		scanf("%d %d",&x,&y);
		v[x].push_back(y);
		v[y].push_back(x);
	}
	dfs(1);
	printf("%lld",ans);
}

猜你喜欢

转载自blog.csdn.net/qq_39529862/article/details/85215441
今日推荐