Codeforces Round #646 (Div. 2) E——Tree Shuffling 思维

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1000005
#define inf 2e9
using namespace std;
inline int read()
{
    int x=0,w=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') w=-1;
        c=getchar();
    }
    while(c<='9'&&c>='0')
    {
        x=(x<<1)+(x<<3)+c-'0';
        c=getchar();
    }
    return w==1?x:-x;
}

ll n,t1,t2,t3,f[maxn],s1[maxn],s2[maxn],ans;
struct node
{
    ll a,b,c,id,w1,w2;
} p[maxn];
vector <int> mp[maxn];

inline void dfs(int u,int fa)
{
    f[u]=fa;
    s1[u]=p[u].w1;//子树中点的权值
    s2[u]=p[u].w2;
    for(int i=0; i<mp[u].size(); i++)
    {
        int v=mp[u][i];
        if(v==fa)
            continue;
        dfs(v,u);
        s1[u]+=s1[v];
        s2[u]+=s2[v];
    }
}
//                        父节点 父节点代价
inline void dfs2(int u,int fa,ll mn)
{
    for(int i=0; i<mp[u].size(); i++)
    {
        int v=mp[u][i];
        if(v==fa)
            continue;
        if(p[u].a<mn) //当前点代价小于父节点
        {
            ll tmp=min(s1[u],s2[u]);
            ans+=tmp*p[u].a*2;
            ans-=tmp*mn*2;
            mn=p[u].a;
        }
        dfs2(v,u,mn);
    }
}

int main()
{
    n=read();
    for(int i=1; i<=n; i++)
    {
        p[i].a=read(),p[i].b=read(),p[i].c=read();
        t1+=p[i].b;
        t2+=p[i].c;
        p[i].id=i;
        if(p[i].b!=p[i].c)//如果需要变换
        {
            if(p[i].b==0) //初始值是0,则需要变成1,就是w1
                p[i].w1=1;
            else
                p[i].w2=1; //初始值是1,需要变成0, 就是w2
        }
    }
    if(t1!=t2)
        return puts("-1"),0;//有的总和 与 要的总和不等 直接结束
    for(int i=1; i<=n-1; i++)
    {
        int u=read(),v=read();
        mp[u].push_back(v);
        mp[v].push_back(u);
    }
    dfs(1,0);
    ans=p[1].a*min(s1[1],s2[1])*2;//直接拿根节点去搞答案
    for(int i=0; i<mp[1].size(); i++)
    {
        int v=mp[1][i];
        dfs2(v,1,p[1].a);
    }
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/QingyuYYYYY/p/13026957.html