//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=1005;
int a[N],fa[N],size[N],visit[N];
int tot,head[N],nxt[N*2],to[N*2];
inline void add(int a,int b){nxt[++tot]=head[a];head[a]=tot;to[tot]=b;}
inline int find(int n,int root){
int node;double maxn=0.0;
for(int i=1;i<=n;++i)
if(!visit[i]&&i!=root&&maxn<(double)a[i]/size[i]){
maxn=(double)a[i]/size[i];node=i;
}
return node;
}
inline void Union(int pre,int node){
a[pre]+=a[node];size[pre]+=size[node];
for(int i=head[node];i;i=nxt[i])fa[to[i]]=pre;
}
inline int solve(int n,int root){
int ans=0;
for(int i=1;i<n;++i){//记得只要n-1次
int node=find(n,root);//找到平均权值最大的点
visit[node]=1;
int pre=fa[node];
while(visit[pre])pre=fa[pre];//找到该点的父亲节点
ans+=a[node]*size[pre];//计算代价
Union(pre,node);//合并
}
return ans+a[root];
}
int main(){
while(1){
int n=read(),root=read();if(!n&&!root)break;
tot=0;memset(head,0,sizeof(head));memset(visit,0,sizeof(visit));
for(int i=1;i<=n;++i)a[i]=read(),size[i]=1;
for(int i=1;i<n;++i){
int x=read(),y=read();
add(x,y);fa[y]=x;
}
printf("%d\n",solve(n,root));
}
return 0;
}
原文:https://www.cnblogs.com/PPXppx/p/11236033.html