bzoj 1827: [Usaco2010 Mar]gather 奶牛大集会

来源:互联网 发布:wp10记录仪软件 编辑:程序博客网 时间:2024/05/22 11:53

→题目链接←


【想说的话】

没有什么想说的=.=

周末没什么事不刷题感觉不太好


【题解】

两遍dfs(树形dp)

将点1当作根

第一遍dfs计算出每个点子节点总数,还有将它作为集会地点时它的子树中的点满足条件需要的代价

第二遍计算出答案,点1的答案就是dfs1时处理出的代价,剩下的点的答案就对于它与它父亲节点的那条边计算一下就好

具体看代码吧


【代码】

#include<bits/stdc++.h>#define MAXN 100010#define ll long long#define inf 1000000000using namespace std;inline int rd(){int x=0,y=1;char c=getchar();while(c<'0' || c>'9'){if(c=='-')y=-y;c=getchar();}while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x*y;}struct node{int to,len;node(int x,int y){to=x,len=y;}};int n;vector<node>v[MAXN];int a[MAXN],fa[MAXN];ll ans[MAXN],sum[MAXN],num[MAXN];ll tot=0;inline void link(int x,int y,int z){v[x].push_back(node(y,z));v[y].push_back(node(x,z));}void dfs1(int x){num[x]=a[x];sum[x]=0;for(int i=0; i<v[x].size(); i++){int to=v[x][i].to;int len=v[x][i].len;if(to==fa[x])continue;fa[to]=x;dfs1(to);num[x]+=num[to];sum[x]+=sum[to]+num[to]*len;}}void dfs2(int x,int len){if(!fa[x])ans[x]=sum[x];else ans[x]=ans[fa[x]]-num[x]*len+(tot-num[x])*len;for(int i=0; i<v[x].size(); i++){int to=v[x][i].to;int len=v[x][i].len;if(fa[x]==to)continue;dfs2(to,len);}}int main(){memset(fa,0,sizeof(fa));n=rd();for(int i=1; i<=n; i++)a[i]=rd(),tot+=a[i];for(int i=1; i<n; i++){int x=rd(),y=rd(),z=rd();link(x,y,z);}dfs1(1);dfs2(1,0);ll Min=(ll)inf*(ll)inf;for(int i=1; i<=n; i++)Min=min(Min,ans[i]);printf("%lld\n",Min);return 0;}


原创粉丝点击