D e s c r i p t i o n Description Description
给定一棵树,规定每个点的权值为其所有叶子节点的权值和,现在只能减少叶子节点的权值,问使所有节点的子节点权值都相同的最少总减少值
数据范围:
对于15%的数据,
1
≤
n
≤
10
1\leq n\leq 10
1≤n≤10。
对于30%的数据,对于边
S
i
,
T
i
,
S
i
+
1
≠
T
i
S_i, T_i,S_i + 1\neq Ti
Si,Ti,Si+1=Ti 的边数不超过3 条。
对于50%的数据,
1
≤
n
≤
1000
1\leq n \leq 1000
1≤n≤1000。
对于100%的数据,
1
≤
n
≤
100000
,
1
<
=
A
i
<
=
2
30
1 \leq n \leq 100000,1 <= A_i <= 2^{30}
1≤n≤100000,1<=Ai<=230
S o l u t i o n Solution Solution
5%贪心
30%搜索
100%树形
d
p
dp
dp
可以发现每次修改结束的值必然是子节点们的
l
c
m
lcm
lcm
代码
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;typedef long long LL;
int n;
vector<int>e[1000011];
LL lim[1000011],ans,a[1000011];
inline LL gcd(LL x,LL y){return y?gcd(y,x%y):x;}
inline LL lcm(LL x,LL y){return x<y?x*y/gcd(y,x):x*y/gcd(x,y);}
inline char Getchar()
{
static char buf[100000],*p1=buf+100000,*pend=buf+100000;
if(p1==pend)
{
p1=buf; pend=buf+fread(buf,1,100000,stdin);
if (pend==p1) return -1;
}
return *p1++;
}
inline LL read()
{
char c;int d=1;LL f=0;
while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register LL x)
{
if(x<0)write(45),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
return;
}
inline void dfs(register int x)
{
lim[x]=1;
if(a[x])return;
int len=e[x].size();
LL sum=0,minn=1e18;
for(register int i=0;i<len;i++)
{
int y=e[x][i];
dfs(y);
lim[x]=lcm(lim[x],lim[y]);
minn=min(minn,a[y]);
sum+=a[y];
}
lim[x]*=len;
a[x]=minn*len-minn*len%lim[x];
ans+=sum-a[x];
return;
}
signed main()
{
freopen("pylon.in","r",stdin);
freopen("pylon.out","w",stdout);
n=read();
for(register int i=1;i<=n;i++) a[i]=read();
for(register int i=1,x,y;i<n;i++)
{
x=read();y=read();
e[x].push_back(y);
}
dfs(1);
write(ans);
}