Hdu 6241 Color a Tree 二分 树形dp传递上下界 2017ccpc哈尔滨

题意:给一棵树每个节点刚开始都是白色的,告诉你A+B中约束条件是,某个子树下至少有多少黑,子树之外最少多少黑,

问你最少的黑点,可以满足这A+B种限定条件

解:

1、子树外的下界在已经确定黑点个数的情况下可以转化为 一个子树的上界,

2、二分黑点的个数,就转化为判定,一个树上的上下界是否都可行的问题。

3、上下界的传递就是 

下界:儿子的下界求和 传递上来,儿子的上界求和+1(本身)在传递上来,最后判定 mid是否在最后root的上下界里面

#include<bits/stdc++.h>
#define en '\n'
#define ll long long
const ll maxn=1e5+10;
using namespace std;
const int inf=0x3f3f3f3f;
ll a[maxn],k,n;
int rd(){int tem;scanf("%d",&tem);return tem;}
vector<int>vec[maxn];
int A[maxn],B[maxn],xia[maxn],shang[maxn],sz[maxn];
void dfs(int x,int f){
    sz[x]=1;
    for(auto y:vec[x]){
        if(y==f)continue;
        dfs(y,x);
        sz[x]+=sz[y];
    }
}
bool dfs2(int x,int f){
    int dd=0,up=1;
    for(auto y: vec[x]){
        if(y==f)continue;
        if(!dfs2(y,x))return 0;
        dd+=xia[y];up+=shang[y];
    }
    xia[x]=max(A[x],dd);
    shang[x]=min(shang[x],up);
    return xia[x]<=shang[x];
}
bool ok(int x){
    for(int i=1;i<=n;i++){
        shang[i]=min(x-B[i],sz[i]);
        if(shang[i]<0)return 0;
    }
    return dfs2(1,0) and xia[1]<=x and shang[1]>=x;
}
signed main()
{
    #ifdef swt
    freopen("input2.txt","r",stdin);
    #endif
    int T;
    cin>>T;
    while(T--){
    cin>>n;
    #define pb push_back
    for(int i=1;i<=n;i++)vec[i].clear(),shang[i]=0,xia[i]=0,A[i]=0,B[i]=0;
    for(int i=1;i<n;i++){int x=rd(),y=rd();vec[x].pb(y),vec[y].pb(x);}
    dfs(1,0);
    int m=rd();
    bool yes=1;
    while(m--){
        int x=rd(),y=rd();
        A[x]=max(A[x],y);
        if(A[x]>sz[x]){
            yes=0;
        }
    }
    m=rd();
    while(m--){
        int x=rd(),y=rd();
        B[x]=max(B[x],y);
        if(B[x]>n-sz[x]){
            yes=0;
        }
    }
    int l=0,r=n;
    while(l<r){
        int mid=(l+r)>>1;
        if(ok(mid)){
            r=mid;
        }else l=mid+1;
    }
    if(!yes){cout<<-1<<en;}
    else cout<<l<<en;
    }
    return  0;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值