【BZOJ1827】【Vijos1487】【Usaco2010 Mar】奶牛聚会

树形DP即可。

我们定义 \displaystyle f(u)=\sum_{v \text{ in }u\text{'s subtree} } c_v \times dis(u,v) \displaystyle g(u)=\sum_{v \text{ isn't in }u\text{'s subtree} } c_v \times dis(u,v)

那么 \displaystyle ans=\min_{1\le u \le n}f(u)+g(u)

接下来考虑怎么求 f g

容易发现 \displaystyle f(u)=\sum_{v\text{ is }u\text{'s child}}f(v)+w(u,v)*sz(v) ,其中 \displaystyle sz(u)=\sum_{v \text{ in }u\text{'s subtree} } c_v

那么 g(u) 怎么求呢?考虑从 g(fa(u))+f(fa(u)) 里减去 u 的子树的贡献,设 \displaystyle sum=\sum_{u=1}^{n} c_u ,我们有:

g(u)=f(fa(u))+g(fa(u))-f(u)-sz(u)*w(u,fa(u))+(sum-sz(u))\times w(u,fa(u))

于是两遍dfs计算 sz f g 就好。

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXSIZE=30000020;
const ll INF=0x3f3f3f3f3f3f3f3fLL;
int bufpos;
char buf[MAXSIZE];
#define NEG 0
void init(){
	#ifdef LOCAL
		freopen("1827.txt","r",stdin);
	#endif
	buf[fread(buf,1,MAXSIZE,stdin)]='\0';
	bufpos=0;
}
#if NEG
int readint(){
	bool isneg;
	int val=0;
	for(;!isdigit(buf[bufpos]) && buf[bufpos]!='-';bufpos++);
	bufpos+=(isneg=buf[bufpos]=='-');
	for(;isdigit(buf[bufpos]);bufpos++)
		val=val*10+buf[bufpos]-'0';
	return isneg?-val:val;
}
#else
int readint(){
	int val=0;
	for(;!isdigit(buf[bufpos]);bufpos++);
	for(;isdigit(buf[bufpos]);bufpos++)
		val=val*10+buf[bufpos]-'0';
	return val;
}
#endif
char readchar(){
	for(;isspace(buf[bufpos]);bufpos++);
	return buf[bufpos++];
}
int readstr(char* s){
	int cur=0;
	for(;isspace(buf[bufpos]);bufpos++);
	for(;!isspace(buf[bufpos]);bufpos++)
		s[cur++]=buf[bufpos];
	s[cur]='\0';
	return cur;
}
const int maxn=100001;
struct graph{
	ll sum;
	int n,m;
	struct edge{
		int to,next,cost;
	}e[maxn*2];
	int first[maxn];
	void addedge(int from,int to,int cost){
		e[++m]=(edge){to,first[from],cost};
		first[from]=m;
	}
	bool vis[maxn];
	ll c[maxn],sz[maxn];
	ll f[maxn],g[maxn];
	void dfs(int u){
		sz[u]=c[u];
		vis[u]=1;
		for(int i=first[u];i;i=e[i].next){
			int v=e[i].to;
			if (vis[v])
				continue;
			dfs(v);
			sz[u]+=sz[v];
			f[u]+=f[v]+sz[v]*e[i].cost;
		}
	}
	void dfs2(int u){
		vis[u]=1;
		//printf("%d\n",u);
		for(int i=first[u];i;i=e[i].next){
			int v=e[i].to;
			//printf("%d\n",v);
			if (vis[v])
				continue;
			g[v]=g[u]+f[u]-f[v]-sz[v]*e[i].cost+(sum-sz[v])*e[i].cost;
			dfs2(v);
		}
	}
	ll work(int n){
		for(int i=1;i<=n;i++)
			sum+=c[i];
		dfs(1);
		memset(vis,0,sizeof(vis));
		dfs2(1);
		ll ans=INF;
		for(int i=1;i<=n;i++){
			//printf("%lld %lld %lld\n",sz[i],f[i],g[i]);
			ans=min(ans,f[i]+g[i]);
		}
		return ans;
	}
}g;
int main(){
	init();
	int n=readint();
	for(int i=1;i<=n;i++)
		g.c[i]=readint();
	for(int i=1;i<n;i++){
		int x=readint(),y=readint(),z=readint();
		g.addedge(x,y,z);
		g.addedge(y,x,z);
	}
	printf("%lld",g.work(n));
}

知识共享许可协议
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。

本文链接:https://www.q234rty.top/2017/09/16/bzoj1827/

隐藏