【树形dp】P2986 [USACO10MAR]Great Cow Gathering G

和上一题的换根树形dp类似,这道就是加上了边权,仍是两次dfs即可

但是这个题的输出会很大,ans初值要赋的大一点(要不然最后两个点会wa)

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
long long n,cnt,head[maxn];
long long  c[maxn],tot,dis[maxn],f[maxn],size[maxn],ans=1000000000000000;
struct edge
{
	int to,nxt,v;
}G[maxn];
void add(int x,int y,int z)
{
	G[++cnt].nxt=head[x]; G[cnt].to=y;
	G[cnt].v=z; head[x]=cnt;
}
void dfs(int u ,int fa)
{
	size[u]=c[u];
	for(int i=head[u];i;i=G[i].nxt)
	{
		int to=G[i].to;
		if(to!=fa)
		{
			dfs(to,u);
			size[u]+=size[to];
			dis[u]+=dis[to]+size[to]*G[i].v;
		}
	}
}
void ddfs(int u,int fa)
{
	for(int i=head[u];i;i=G[i].nxt)
	{
		int to=G[i].to;
		if(to!=fa)
		{
			f[to]=f[u]-size[to]*G[i].v+(tot-size[to])*G[i].v;
			ans=min(ans,f[to]);
			ddfs(to,u);
		}
	}
}
signed main()
{
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	scanf("%lld",&n);
	long long x,y,z;
	for(int i=1;i<=n;i++) scanf("%lld",&c[i]),tot+=c[i];
	for(int i=1;i<n;i++)
	{
		scanf("%lld%lld%lld",&x,&y,&z);
		add(x,y,z); add(y,x,z);	
	}
	dfs(1,1);
	f[1]=dis[1];
	ans=min(ans,f[1]);
	ddfs(1,1);
	printf("%lld\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/andyc_03/article/details/107678531