题:https://codeforces.com/contest/1363/problem/E
题意:给定一棵树,每个节点有ai,bi,ci的属性,代表节点 i 想将自己的bi 通过和自己子树的 值交换而变成ci。类似地,这种交换的代价为2*ai。允许的操作为选择一个节点x,可以选择任意k个该子树节点数,进行这种交换。问最小代价或输出-1代表不能达到要求。
分析:题目中c的取值为0或1,若能达到要求就表示整个树0->1 和1->0的对数要一样。接着就可以递归地让最小的消耗去完成交换对数,这个对数不是选0->1就是选1->0,所以只要取俩者最小即可。
#include<bits/stdc++.h> using namespace std; #define pb push_back typedef long long ll; const int inf=0x3f3f3f3f; const ll INF=1e18; const int M=2e5+5; vector<int>g[M]; ll dp[M],a[M]; int b[M],c[M],cnt[M][2]; void py(){ cout<<"Yes"<<' '; } void pn(){ cout<<"No"<<' '; } ll ksm(ll x,ll y){ ll t=1ll; while(y){ if(y&1) t=t*x; y>>=1; x=x*x; } return t; } ll ans; void dfs(int u,int fa){ if(fa) a[u]=min(a[u],a[fa]); int flag=-1; if(!b[u]&&c[u]) flag=0; if(b[u]&&!c[u]) flag=1; int countt0=0,countt1=0; for(auto v:g[u]){ if(v!=fa){ dfs(v,u); cnt[u][0]+=cnt[v][0]; cnt[u][1]+=cnt[v][1]; int tmp=cnt[v][0]-cnt[v][1]; if(tmp>0) countt0+=tmp; else countt1-=tmp; } } if(flag==0) cnt[u][0]++,countt0++; if(flag==1) cnt[u][1]++,countt1++; ///cout<<u<<"!!!"<<countt0<<"!!"<<countt1<<endl; ///cout<<a[u]<<"@@"<<ans<<endl; ans+=2ll*a[u]*min(countt1,countt0); } int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld%d%d",&a[i],&b[i],&c[i]),dp[i]=INF; for(int u,v,i=1;i<n;i++){ scanf("%d%d",&u,&v); g[u].pb(v),g[v].pb(u); } dfs(1,0); printf("%lld ",cnt[1][0]!=cnt[1][1]?-1:ans); return 0; }