• 【luoguP2986】[USACO10MAR]伟大的奶牛聚集Great Cow Gathering


    题目链接

    先把(1)作为根求每个子树的(size),算出把(1)作为集会点的代价,不难发现把集会点移动到(u)的儿子(v)上后的代价为原代价-(v)(size)*边权+(总的(size)-(v)(size))*边权

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define int long long
    using namespace std;
    
    const int MAXN=100010;
    const int MAXM=200010;
    
    int n,a[MAXN],size[MAXN],dep[MAXN];
    
    int Head[MAXN],num;
    struct NODE{
    	int to,w,nxt;
    } e[MAXM];
    
    inline void add(int x,int y,int z){
    	e[++num].to=y;
    	e[num].w=z;
    	e[num].nxt=Head[x];
    	Head[x]=num;
    }
    
    void dfs1(int x,int fa){
    	size[x]=a[x];
    	for(int i=Head[x];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(v==fa) continue;
    		dep[v]=dep[x]+e[i].w;
    		dfs1(v,x);
    		size[x]+=size[v];
    	}
    }
    
    int Ans=1e18;
    
    void dfs2(int x,int fa,int Sum){
    	Ans=min(Ans,Sum);
    	for(int i=Head[x];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(v==fa) continue;
    		dfs2(v,x,Sum+e[i].w*(size[1]-2*size[v]));
    	}
    }
    
    signed main()
    {
    	scanf("%lld",&n);
    	for(int i=1;i<=n;++i)
    		scanf("%lld",&a[i]);
    	int x,y,z;
    	for(int i=1;i<n;++i){
    		scanf("%lld%lld%lld",&x,&y,&z);
    		add(x,y,z); add(y,x,z);
    	}
    	dfs1(1,0);
    	int Sum=0;
    	for(int i=1;i<=n;++i)
    		Sum+=dep[i]*a[i];
    	dfs2(1,0,Sum);
    	printf("%lld
    ",Ans);
    	return 0;
    }
    
  • 相关阅读:
    代码品质
    窖藏好题
    最后一次模拟
    几个有意思的题目
    【数组练习】
    【复习】图论
    【复习】后缀数组
    The Usage Of Difference Table
    【复习】NTT注意事项
    CF999E Reachability from the Capital
  • 原文地址:https://www.cnblogs.com/yjkhhh/p/11743833.html
Copyright © 2020-2023  润新知