话不多说,请看代码与注释
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<vector>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define endl "\n"
using namespace std;
const int N = 2e5+5;
ll a[N], b[N], c[N], ans;
ll dp[N][2]={0}, f[N]={0};
vector<ll> e[N];
void dfs(ll i,ll fa)//第一遍搜索
{
for(int j=0;j<e[i].size();++j)
{
if(e[i][j]!=fa)
{
a[e[i][j]] = min(a[e[i][j]],a[i]);
//在从祖先结点到孩子结点中进行遍历
//确认当要修改一个值时 选取哪个点进行消耗最小
dfs(e[i][j],i);
}
}
}
void dfss(ll i,ll fa)//第二遍搜索
{
if(b[i]!=c[i])//需要把值修改为b[i]的结点数增加
{
dp[i][b[i]]++;
}
for(int j=0;j<e[i].size();++j)
{
if(e[i][j]!=fa)
{
dfss(e[i][j],i);
dp[i][1] += dp[e[i][j]][1];//统计子树的情况
dp[i][0] += dp[e[i][j]][0];
}
}
ll k = min(dp[i][1],dp[i][0]);//贪心处理数目更小的一种
ans += k*a[i]*2;//计入答案
dp[i][1] -= k;//修改仍有问题的结点数目
dp[i][0] -= k;
}
int main()
{
int n;
scanf("%d",&n);
ll s1 = 0, s2 = 0;
for(int i=1;i<=n;++i)
{
scanf("%lld %lld %lld",&a[i],&b[i],&c[i]);
s1 += b[i];
s2 += c[i];
f[i] = 0;
}
for(int i=1;i<n;++i)//建树
{
int u, v;
scanf("%lld %lld",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
if(s1!=s2)//1的数目不同
{
cout << -1 << endl;//无法实现
}
else
{
ans = 0;
dfs(1,0);
dfss(1,0);
printf("%lld\n",ans);
}
return 0;
}