zoukankan      html  css  js  c++  java
  • CF1363E Tree Shuffling(贪心+树上乱搞)

    对于一些不符合的点来说,肯定是被他的父节点上权值最小的点转换最好。

    首先我们先排除不可能情况也就是01不等

    之后发现,交换完两个数后,0不符合的和1不符合的个数各自-1,因此不会影响其他交换

    因此我们维护一个最小值,表示父亲节点的最小值,如果这个值比当前节点小,那么显然在子树内部交换更好

    之后只要dfs维护一下需要交换的01个数就好

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4e5+10;
    typedef long long ll;
    int h[N],ne[N],e[N],idx;
    ll a[N],b[N],c[N];
    int cnt0[N],cnt1[N];
    ll res;
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    void dfs(int u,int fa,ll tmp){
        ll mi=min(tmp,a[u]);
        int i;
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(j==fa)
                continue;
            dfs(j,u,mi);
            cnt0[u]+=cnt0[j];
            cnt1[u]+=cnt1[j];
        }
        if(b[u]!=c[u]){
            if(b[u]==1)
                cnt1[u]++;
            else{
                cnt0[u]++;
            }
        }
        int x=min(cnt1[u],cnt0[u]);
        if(mi==a[u]){
            cnt1[u]-=x;
            cnt0[u]-=x;
            res+=2*x*a[u];
        }
    }
    int main(){
        int n;
        cin>>n;
        memset(h,-1,sizeof h);
        int i;
        int tmp1=0,tmp2=0;
        for(i=1;i<=n;i++){
            scanf("%lld%lld%lld",&a[i],&b[i],&c[i]);
            if(b[i])
                tmp1++;
            if(c[i])
                tmp2++;
        }
        for(i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        if(tmp1!=tmp2){
            cout<<"-1"<<endl;
        }
        else{
            dfs(1,-1,a[1]);
            cout<<res<<endl;
        }
    }
    View Code
  • 相关阅读:
    455. Assign Cookies(分饼干)(leetcode)
    栈的压入、弹出序列 (剑指offer)
    第五届蓝桥杯c/c++B组1
    第六届蓝桥杯试题c/c++B组8
    第六届蓝桥杯试题c/c++B组7
    第六届蓝桥杯试题c/c++B组6
    第六届蓝桥杯试题c/c++B组5
    第六届蓝桥杯试题c/c++B组4
    第六届蓝桥杯试题c/c++B组3
    第六届蓝桥杯试题c/c++B组2
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13233034.html
Copyright © 2011-2022 走看看