题目链接

Solution

辣鸡题…因为一个函数名看了我贼久。
思路很简单,可以先随便指定一个根,然后考虑换根的变化。
每一次把根从 \(x\) 换成 \(x\) 的一个子节点 \(y\),记录一下每个节点的子树牛数目 \(son\)
\(sum\) 为所有节点上牛的数目,那么每一次换根变化为 \((sum-son_y*2)*w\)
然后就可以统计了,复杂度 \(O(n)\)

Code

#include<bits/stdc++.h>
#define N 100008
#define ll long long
using namespace std;

void in(ll &x)
{
    char ch=getchar();ll f=1,w=0;
    while(ch<\'0\'||ch>\'9\'){if(ch==\'-\')f=-1;ch=getchar();}
    while(ch<=\'9\'&&ch>=\'0\'){w=w*10+ch-\'0\';ch=getchar();}
    x=f*w; return;
}

struct sj{
    ll to,next,w;
}a[N*2];
ll head[N],size,c[N],n;

void add(ll x,ll y,ll z)
{   
    a[++size].to=y;
    a[size].next=head[x];
    head[x]=size;
    a[size].w=z;
}

ll sum[N],son[N],ans[N],som[N],Ans,Sum;
void dfs(ll x,ll fr)
{
    son[x]=c[x];
    for(ll i=head[x];i;i=a[i].next)
    {
        ll tt=a[i].to;
        if(tt==fr)continue;
        dfs(tt,x);
        son[x]+=son[tt];
        sum[x]+=(a[i].w*son[tt]+sum[tt]);   
    }
}

void work(ll x,ll fr)
{
    for(ll i=head[x];i;i=a[i].next)
    {
        ll tt=a[i].to;
        if(tt==fr)continue;
        som[tt]=Sum-son[tt];
        ans[tt]=ans[x]+som[tt]*a[i].w-son[tt]*a[i].w;
		Ans=min(Ans,ans[tt]);  
		work(tt,x);
    }
}

int main()
{
    in(n);
    for(ll i=1;i<=n;i++) in(c[i]),Sum+=c[i];
    for(ll i=1;i<n;i++)
    {
        ll x,y,w;
        in(x),in(y),in(w);
        add(x,y,w),add(y,x,w);
    }
    dfs(1,0); Ans=0x3f3f3f3f3f3f3f;
    ans[1]=sum[1]; work(1,0);
    cout<<min(ans[1],Ans)<<endl;
    return 0;
}

版权声明:本文为Kv-Stalin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/Kv-Stalin/p/11234590.html