cf 646 E. Tree Shuffling

貪心做,每次選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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章