原题链接
给你n个节点,根节点为1,第i个节点花费a_i,装入了数字b_i,它想要最后将数字c_i最后写入第i个节点。
你有一种操作,就是使得u节点的子树的k个节点进行交换,产生的花费为k*a_u,求最小花费
解法:考虑树形dp,题目已知1为根节点,我们可以从上往下遍历,维护一个a[i]的最小值,如果当前遍历节点的值a[i]为最小值,那么就是当前的进行修改花费是最少的,更新答案即可,注意一点更新完之后,1号节点还有剩余未匹配节点,说明无法进行交换输出-1
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define sc scanf
#define pr printf
#define INF 0x3f3f3f3f
const int maxn = 2e5 + 5;
vector<int>g[maxn];
ll dp[maxn][2];
struct node{
ll a,b,c;
}a[maxn];
ll ans;
void dfs(int u, int fa, ll mn){
mn = min(mn, a[u].a);
for(int i = 0; i < g[u].size(); i++){
int j = g[u][i];
if(j == fa)continue;
dfs(j, u, mn);
dp[u][0] += dp[j][0];
dp[u][1] += dp[j][1];
}
if(a[u].b != a[u].c){
if(a[u].b == 1)dp[u][1]++;
else dp[u][0]++;
}
if(a[u].a == mn){
ll s = min(dp[u][0],dp[u][1]);
ans += s*2*a[u].a;
dp[u][1] -= s;
dp[u][0] -= s;
}
}
void solve(){
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%lld%lld%lld",&a[i].a,&a[i].b,&a[i].c);
}
for(int i = 1; i < n; i++){
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, 0, INF);
if(dp[1][1] || dp[1][0])printf("-1\n");
else printf("%lld\n",ans);
}
int main(){
int t;
t = 1;
while(t--)
solve();
}