HDU5682 zxa and leaf(二分)

这道题很容易看出是求最大值的最小值,然后我们发现每个边的取值范围都是一段区间,这就是常见的用区间表示是否满足题意,当左边界大于右边界的时候就不满足

#include<iostream>
#include<queue>
#include<map>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<stack>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
int n,k;
vector<int> g[N];
struct node{
    int l,r;
    int t1,t2;
}tr[N];
void init(){
    int i;
    for(i=0;i<=n;i++){
        tr[i].l=1;
        tr[i].r=inf;
        g[i].clear();
    }
}
bool dfs(int u,int fa,int x){
    tr[u].t1=tr[u].l;
    tr[u].t2=tr[u].r;
    int i;
    for(i=0;i<g[u].size();i++){
        int j=g[u][i];
        if(j==fa)
            continue;
        if(!dfs(j,u,x))
            return false;
        tr[u].t1=max(tr[u].t1,max(1,tr[j].t1-x));
        tr[u].t2=min(tr[u].t2,min(inf,tr[j].t2+x));
        if(tr[u].t1>tr[u].t2)
            return false;
    }
    return true;
}
bool check(int mid){
    return dfs(1,-1,mid);
}
int main(){
    int t;
    cin>>t;
    while(t--){
        cin>>n>>k;
        init();
        int i;
        for(i=0;i<n-1;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        for(i=0;i<k;i++){
            int u,w;
            scanf("%d%d",&u,&w);
            tr[u].l=tr[u].r=w;
        }
        int l=0,r=inf;
        while(l<r){
            int mid=l+r>>1;
            if(check(mid))
                r=mid;
            else
                l=mid+1;
        }
        cout<<l<<endl;
    }
}
View Code

 

posted @ 2020-03-08 10:19  朝暮不思  阅读(107)  评论(0)    收藏  举报