zoukankan      html  css  js  c++  java
  • HDU 5682 zxa and leaf

    题目链接:

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

    题意:

    选择一些节点的beautiful值,让所有边相连的两个端点的beatiful值的差的绝对值的最大值最小

    题解:

    一看到让最大值最小,或者最小值最大就应该想到二分法。

    这样就能把问题变为判定性问题,往往能够在一定程度上降低算法的复杂度,并且效率还比较 高。

    这题,二分完答案之后我们就能够根据叶子节点的取值范围递推出所有点的取值范围,如果所有节点的取值范围都不为空,则上限还能更小。

    初始化:

    有输入beautiful值得叶子节点范围为[x,x],剩下的都为[1,10^9]。

    代码:

    #pragma comment(linker, "/STACK:102400000,102400000") 
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 5e4 + 10;
    const int INF = 1e9;
    
    struct Node {
        int L, R;
        int l, r;
    }nds[maxn];
    
    int n, k;
    vector<int> G[maxn];
    
    int _ans;
    bool dfs(int u, int fa) {
        nds[u].l = nds[u].L, nds[u].r = nds[u].R;
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i];
            if (v == fa) continue;
            if (!dfs(v, u)) return false;
            nds[v].l = max(1, nds[v].l - _ans);
            nds[v].r = min(INF, nds[v].r + _ans);
            nds[u].l = max(nds[u].l, nds[v].l);
            nds[u].r = min(nds[u].r, nds[v].r);
            if (nds[u].l > nds[u].r) return false;
        }
        return true;
    }
    
    void init() {
        for (int i = 1; i <= n; i++) {
            nds[i].L = 1;
            nds[i].R = INF;
            G[i].clear();
        }
    }
    
    int main() {
        int tc;
        scanf("%d", &tc);
        while (tc--) {
            scanf("%d%d", &n, &k);
            init();
            for (int i = 1; i < n; i++) {
                int u, v;
                scanf("%d%d", &u, &v);
                G[u].push_back(v);
                G[v].push_back(u);
            }
            for (int i = 0; i < k; i++) {
                int p, v;
                scanf("%d%d", &p, &v);
                nds[p].L = nds[p].R = v;
            }
            int l = -1, r = INF;
            while (l < r - 1) {
                _ans = l + (r - l) / 2;
                if (dfs(1,-1)) r = _ans;
                else l=_ans;
            }
            printf("%d
    ", r);
        }
        return 0;
    }
  • 相关阅读:
    golang 用tar打包文件或文件夹
    golang 最和谐的子序列
    golang 轮训加密算法
    golang map
    golang 队列
    golang 栈操作
    golang 多维数组
    golang 数组反转
    c# sendmessage control to scroll
    c# 启动的时候向其他程序传值
  • 原文地址:https://www.cnblogs.com/fenice/p/5541594.html
Copyright © 2011-2022 走看看