hdu 5682 zxa and leaf (二分+搜索)

来源:互联网 发布:2017全球互联网数据 编辑:程序博客网 时间:2024/05/23 17:55

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

题意:给你一个无根树,然后有一些叶子节点,其中k个给定值,其余节点的值不知道,然后让你设置其他节点的值,让每条边的值的最大值最小(边的值为两点的值的差的绝对值)

题解:最大值最小,二分呗,然后怎么弄呢,我开头想的是每个叶子到根有个值域,然后找值域是否矛盾,后来发现不行,也许两个节点不到根的时候就相遇了,他们矛盾,但是走到根,值域扩大了,就不矛盾了,所以应该每次二分了,都搜索一次,类似树形dp,维护每个节点的可行的值域,如果不可行,return false;

 

#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <sstream>#include <cstdlib>#include <iostream>#include <algorithm>#pragma comment(linker,"/STACK:102400000,102400000")using namespace std;#define   MAX           50005#define   MAXN          1000005#define   maxnode       10#define   sigma_size    2#define   lson          l,m,rt<<1#define   rson          m+1,r,rt<<1|1#define   lrt           rt<<1#define   rrt           rt<<1|1#define   middle        int m=(r+l)>>1#define   LL            long long#define   ull           unsigned long long#define   mem(x,v)      memset(x,v,sizeof(x))#define   lowbit(x)     (x&-x)#define   pii           pair<int,int>#define   bits(a)       __builtin_popcount(a)#define   mk            make_pair#define   limit         10000//const int    prime = 999983;const int    INF   = 0x3f3f3f3f;const LL     INFF  = 0x3f3f;const double pi    = acos(-1.0);const double inf   = 1e18;const double eps   = 1e-9;const LL     mod   = 1e9+7;const ull    mxx   = 1333331;/*****************************************************/inline void RI(int &x) {      char c;      while((c=getchar())<'0' || c>'9');      x=c-'0';      while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';}/*****************************************************/struct Edge{    int v,next;}edge[MAX*2];int head[MAX];LL ll[MAX];LL rr[MAX];int deg[MAX];int vis[MAX];int tot;int n,k;int root;void init(){    mem(head,-1);    mem(deg,0);    mem(vis,0);    tot=0;}void add_edge(int a,int b){    edge[tot].v=b;    edge[tot].next=head[a];    head[a]=tot++;}bool dfs(int u,int fa,int x){    for(int i=head[u];i!=-1;i=edge[i].next){        int v=edge[i].v;        if(v==fa) continue;        if(!dfs(v,u,x)) return false;        LL l=ll[v]-x;        LL r=rr[v]+x;        //if(x==1) cout<<l<<" "<<r<<" "<<ll[u]<<" "<<rr[u]<<" "<<u<<endl;        if(l>rr[u]||r<ll[u]) return false;        ll[u]=max(ll[u],l);        rr[u]=min(rr[u],r);    }    return true;}bool check(int x){    for(int i=1;i<=n;i++){        if(vis[i]) continue;        ll[i]=-1e17;        rr[i]=1e17;    }    if(dfs(root,-1,x)) return true;    return false;}int main(){    //freopen("in.txt","r",stdin);    int t;    cin>>t;    while(t--){        cin>>n>>k;        init();        for(int i=1;i<n;i++){            int a,b;            scanf("%d%d",&a,&b);            add_edge(a,b);            add_edge(b,a);            deg[a]++;            deg[b]++;        }        while(k--){            int a,b;            scanf("%d%d",&a,&b);            ll[a]=b;            rr[a]=b;            vis[a]=1;        }        root=1;        for(int i=1;i<=n;i++){            if(deg[i]!=1){                root=i;                break;            }        }        int l=0,r=INF;        while(l<=r){            int mid=(l+r)/2;            //if(mid<10) cout<<mid<<endl;            if(check(mid)) r=mid-1;            else l=mid+1;        }        cout<<l<<endl;    }    return 0;}

0 0
原创粉丝点击