Hdu 6241 二分+树形dp

来源:互联网 发布:unity3d 虚拟拆装 编辑:程序博客网 时间:2024/06/10 09:06

这是哈尔滨的L题。只要想到二分答案就很水了。总数确定后每个子树有一个区间,树dp合并这个区间,一旦有空区间就不够。需要注意的是要特判下根节点的最大值是否能取到二分的答案。
代码:

#include <bits/stdc++.h>using namespace std;const int maxn=100007;struct edge{    int to, next;}e[maxn*2];int head[maxn];int cnt;void init(){    cnt=0;    memset(head, -1, sizeof(head));}void add(int u, int v){    e[cnt].to=v;    e[cnt].next=head[u];    head[u]=cnt++;}int n, a[maxn], b[maxn];long long mn[maxn], mx[maxn];bool flag;void dfs(int u, int fa){    long long mnsum=0, mxsum=1;    for(int i=head[u];~i;i=e[i].next){        int v=e[i].to;        if(v==fa)continue;        dfs(v, u);        mnsum+=mn[v];        mxsum+=mx[v];    }    mn[u]=max(mn[u], mnsum);    mx[u]=min(mx[u], mxsum);    if(mn[u]>mx[u])flag=false;}bool check(int mid){    for(int i=1;i<=n;i++){        mn[i]=a[i], mx[i]=mid-b[i];        if(mn[i]>mx[i])return false;    }    flag=true;    dfs(1, 0);    if(mx[1]<mid)return false;    //若无特判下面数据会跪    //1    //3    //1 2    //1 3    //1    //1 1    //1    //1 1    return flag;}int main(){    int T;    scanf("%d", &T);    while(T--){        init();        scanf("%d", &n);        for(int i=1;i<n;i++){            int u, v;            scanf("%d%d", &u, &v);            add(u, v);            add(v, u);        }        memset(a, 0, sizeof(a));        memset(b, 0, sizeof(b));        int q;        scanf("%d", &q);        for(int i=1;i<=q;i++){            int id, num;            scanf("%d%d", &id, &num);            a[id]=max(a[id], num);        }        scanf("%d", &q);        for(int i=1;i<=q;i++){            int id, num;            scanf("%d%d", &id, &num);            b[id]=max(b[id], num);        }        if(!check(n)){            printf("-1\n");        }        else {            int l=0, r=n, tag=-1;            while(l<=r){                if(r-l<=1){                    if(check(l))tag=l;                    else tag=r;                    break;                }                int mid=(l+r)/2;                if(check(mid))r=mid;                else l=mid;            }            printf("%d\n", tag);        }    }}
原创粉丝点击