贪心做,每次选ai最小的点向下遍历,然后做最大交换次数。 把剩余的(1个0或1个1存在根结点) 在继续这个过程就行 我们可以推断 走过的点一定不会再走(再走肯定不会更优)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
ll a[N];
int fa[N],b[N],c[N],cur,h[N],nex[N<<1],to[N<<1],vis[N],re[N][2];
ll ans;
void add_edge(int x,int y){
to[++cur]=y;nex[cur]=h[x];h[x]=cur;
}
void dfs(int u,int f){
fa[u]=f;
for(int i = h[u]; i; i=nex[i]){
if(f!=to[i]){
dfs(to[i],u);
}
}
}
void dfs1(int rt,int u){
if(vis[u]) return;
vis[u]=1;
re[rt][0]+=(b[u]!=c[u]&&(b[u]==0));
re[rt][1]+=(b[u]!=c[u]&&(b[u]==1));
for(int i = h[u]; i; i = nex[i]){
int v = to[i];
if(v!=fa[u]&&vis[to[i]]){
re[rt][0]+=re[to[i]][0];
re[rt][1]+=re[to[i]][1];
}
if(v!=fa[u]&&!vis[to[i]]){
dfs1(rt,v);
}
}
}
struct node{
ll a;
int b,c,id;
bool operator <(const node &x) const{
return a<x.a;
}
}q[N];
int main(){
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%lld%d%d",&q[i].a,&q[i].b,&q[i].c);
a[i]=q[i].a,b[i]=q[i].b,c[i]=q[i].c;
q[i].id=i;
}
sort(q+1,q+1+n);
for(int i = 1; i <= n-1; i++){
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
int z=0,o=0;
for(int i = 1; i <= n; i++){
z+=(q[i].b!=q[i].c&&(q[i].b==0));
o+=(q[i].b!=q[i].c&&(q[i].b==1));
}
//printf("z=%d o=%d\n",z,o);
if(z!=o){
printf("-1");
return 0;
}
dfs(1,0);
for(int i = 1; i <= n; i++){
dfs1(q[i].id,q[i].id);
int j = min(re[q[i].id][0],re[q[i].id][1]);
ans+=2ll*j*q[i].a;
re[q[i].id][0]-=j;
re[q[i].id][1]-=j;
}
printf("%lld\n",ans);
return 0;
}