以太运输计划??

米特运输
这题翻译题面很重要
给出一棵树以及上面点的点权
要求修尽可能少的点,使树上所有点满足条件
1.每个点的点权=其儿子的点权和
2.其所有儿子点权相等
由于一边去乐园旅游一边打题,对题目理解不深刻,故写题解复习
定义f数组记录每个点保持其点权时,根节点的点权
由于cs没准备好,先写一下转移方程
in数组表示一个点有几个儿贼(如果用vector就当我放屁)

[f[x]=a[x]*prod in[fa] ]

注意(prod in[fa])是x的所有祖先in值之积
得每个点的点权都被根节点安排的明明白白——只由根节点决定
最后肯定是f相等的点越多越好了(需要更改的点更少)
in_tree.png
f_tree.png

#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;
}
原文地址:https://www.cnblogs.com/caijiLYC/p/13417191.html