米特运输
这题翻译题面很重要
给出一棵树以及上面点的点权
要求修尽可能少的点,使树上所有点满足条件
1.每个点的点权=其儿子的点权和
2.其所有儿子点权相等
由于一边去乐园旅游一边打题,对题目理解不深刻,故写题解复习
定义f数组记录每个点保持其点权时,根节点的点权
由于cs没准备好,先写一下转移方程
in数组表示一个点有几个儿贼(如果用vector就当我放屁)
[f[x]=a[x]*prod in[fa]
]
注意(prod in[fa])是x的所有祖先in值之积
得每个点的点权都被根节点安排的明明白白——只由根节点决定
最后肯定是f相等的点越多越好了(需要更改的点更少)
#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
#define ld long double
#define N 510000
using namespace std;
ll n,in[N],head[N],cnt,ret,ans;
ld f[N],a[N];
struct Star_Plstinum{
ll to,nxt;
}q[N*10];
void add(ll u,ll v){
q[++cnt].to=v;
q[cnt].nxt=head[u];
head[u]=cnt;
}
void dfs(ll x,ll fa,ld sum){
f[x]=sum+log(a[x]);
for(ll i=head[x];i;i=q[i].nxt){
ll v=q[i].to;
if(v!=fa){
dfs(v,x,sum+log(in[x]));
}
}
}
int main(){
cin>>n;
for(ll i=1;i<=n;i++){
scanf("%Lf",&a[i]);
}
for(ll i=1;i<n;i++){
ll a1,a2;
scanf("%lld%lld",&a1,&a2);
add(a1,a2),add(a2,a1);
in[a1]++;
}
dfs(1,0,0);
sort(1+f,1+f+n);
ret=1;
for(ll i=2;i<=n;i++){
if(f[i]-f[i-1]<=1e-9){
ret++;
ans=max(ret,ans);
}
else ret=1;
}
cout<<n-ans;
}