Description
Data Constraint
Data Constraint
对于20%的数据,N<=15
对于100%的数据,T<=10,N<=100,0<=si<=10000,1<=X,Y<=N,1<=Z<=10000。
Solution
经过观察可以发现,每一种平衡状态一定是由sum个x和sum1个x+1组成的。
其中sum1=∑ainsum1=\frac{\sum a_{i}}{n}sum1=n∑ai
sum=n−sum1sum=n-sum1sum=n−sum1
可以考虑树型dp。
设f[i][j]f[i][j]f[i][j]表示以iii号节点为根的子树油桶数为x+1x+1x+1的节点数为jjj的最小代价
那么状态转移方程为:
f[i][j]=min(f[i][j−k]+f[son][k]+abs(s[i]−x∗(size[son]−j)−(x+1)∗j)∗len)f[i][j]=min(f[i][j-k]+f[son][k]+abs(s[i]-x*(size[son]-j)-(x+1)*j)*len)f[i][j]=min(f[i][j−k]+f[son][k]+abs(s[i]−x∗(size[son]−j)−(x+1)∗j)∗len)
其中s[i]s[i]s[i]为以i为根的子树中总的初始油桶数量,size[son]size[son]size[son]表示以sonsonson为根的子树的节点数。这句话的意思就是把儿子多出来的运到父亲这,如果儿子少了,就是从父亲这运过来,所以要取绝对值。
这道题还可以用费用流做,只不过我太弱,不会做。
Code
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define ll long long
using namespace std;
int T,n,cnt,sum,val,val1,Size;
int a[101],head[101],size[101];
ll s[101],f[101][101],g[101];
struct node {
int to,len,next;
}edge[201];
inline int read() {
int s=0;
char ch=getchar();
while(ch<48||ch>57)ch=getchar();
while(ch>=48&&ch<=57)
s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
return s;
}
inline void add(int x,int y,int z) {
edge[cnt]=(node){y,z,head[x]};
head[x]=cnt++;
}
inline void dfs(int now,int fa) {
size[now]=1;s[now]=a[now];
f[now][0]=f[now][1]=0;
for(int i=head[now];i!=-1;i=edge[i].next) {
int son=edge[i].to;
if(son==fa)continue;
dfs(son,now);
}
for(int i=head[now];i!=-1;i=edge[i].next) {
int son=edge[i].to,len=edge[i].len;
if(son==fa)continue;
size[now]+=size[son];
s[now]+=s[son];
memset(g,0x7f7f7f7f,sizeof(g));
for(int j=0;j<=Size&&j<=size[now];++j)
for(int k=0;k<=size[son]&&k<=j;++k)
g[j]=min(g[j],f[now][j-k]+f[son][k]+abs(s[son]-(size[son]-k)*val-k*(val+1))*len);
//不能直接转移,要把所有答案存下来再转移过去。不然会重复
for(int j=0;j<=Size&&j<=size[now];j++)f[now][j]=g[j];
}
}
int main() {
T=read();
while(T--) {
n=read();cnt=0;sum=0;
for(int i=1;i<=n;++i)
a[i]=read(),sum+=a[i],head[i]=-1;
Size=sum%n;val=sum/n;
for(int i=1;i<n;++i) {
int u=read(),v=read(),w=read();
add(u,v,w);add(v,u,w);
}
memset(f,0x7f7f7f7f,sizeof(f));
dfs(1,0);
printf("%lld\n",f[1][Size]);
}
}