• hdu6241(给定树中向上向下限制求最小可能个数)


    题:http://acm.hdu.edu.cn/showproblem.php?pid=6241

    题意:给定n个点的树,给定A约束和B约束,[x,y]分别表示以x为子树的节点至少要有y个黑点,除x子树外的节点至少有y个节点,问满足所有约束的最少黑点数是多少,不存在则输出-1

    分析:二分答案,关键是把B约束转化为x子树,那就让二分答案转化B约束;

       具体地,让B约束变为x子树最多能有多少个黑点,那么A就是下界,B就是上界;

       check就用dfs不断地最小代价地减少上界,若最终上界仍然大于下界,且mid在俩者(根节点的上下界)之间,则return true。

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    const int M=1e5+5;
    int sz[M],A[M],B[M],fir[M],sec[M],n,m1,m2;
    vector<int>g[M];
    void dfs1(int u,int fa){
        sz[u]=1;
        int cnt=0;
        for(auto v:g[u]){
            if(v!=fa){
                dfs1(v,u);
                sz[u]+=sz[v];
                cnt+=A[v];
            }
        }
        A[u]=max(A[u],cnt);
    }
    bool dfs2(int u,int fa){
        int cnt=0;
        for(auto v:g[u]){
            if(v!=fa){
                if(!dfs2(v,u)) return false;
                cnt+=B[v];
            }
        }
        B[u]=min(B[u],cnt+1);
        if(A[u]>B[u])return false;
        return true;
    }
    bool check(int mid){
        for(int i=1;i<=n;i++)  B[i]=sz[i];
        for(int i=1;i<=m2;i++) B[fir[i]]=min(B[fir[i]],mid-sec[i]);
        if(dfs2(1,0)&&A[1]<=mid&&mid<=B[1]) return true;
        return false;
    }
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            for(int i=1;i<=n;i++) g[i].clear(),A[i]=0,B[i]=0;
            for(int u,v,i=1;i<n;i++){
                scanf("%d%d",&u,&v);
                g[u].pb(v);
                g[v].pb(u);
            }
            scanf("%d",&m1);
            while(m1--){
                int x,y;
                scanf("%d%d",&x,&y);
                A[x]=max(A[x],y);
            }
            dfs1(1,0);
            scanf("%d",&m2);
            for(int i=1;i<=m2;i++) scanf("%d%d",&fir[i],&sec[i]);
            int l=1,r=n,ans=-1;
            while(l<=r){
                int midd=(l+r)>>1;
                if(check(midd)){
                    ans=midd;
                    r=midd-1;
                }
                else
                    l=midd+1;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    AC自动机
    KMP、扩展KMP、MANACHER
    Docker用户身份登录和管理员权限
    Response.Redirect和Server.Transfer比较--(转)
    SQLServer中char、varchar、nchar、nvarchar的区别--(转)
    MsSQL的字段类型--(转)
    读取UEditor编辑框内容到数据库和上传图片的配置
    以做产品的思想分析男女相处之道
    springBoot创建定时任务
    Runnable和Thread的区别
  • 原文地址:https://www.cnblogs.com/starve/p/13849987.html
Copyright © 2020-2023  润新知