• 牛客 msc的宠物 【二分+树形dp】


    题目链接
    自己假自己,怎么写都只能过一半的测试点,学了别人的题解。
    题目描述
    给定一棵树,每个结点有一个权值,求(k+1)个连通块中最值之差的最小值是多少。
    思路
    二分答案很显然,主要是用树形dp计算最少需要的次数。
    (dp[u][i]):结点(u)的值(a[u])在范围为([a_i,a_i + mid])中,且满足其子树所有点的值在该范围中时需要删除的边数。
    (f[u]):结点(u)所需要删除的最少的边的数量。
    转移方程:(dp[u][i]=min(dp[v][i],f[v]+1))
    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    const int inf = 0x3f3f3f3f;
    const int N = 1010;
    LL dp[N][N], f[N];
    LL a[N];
    vector<int> e[N];
    int n, k;
    
    void dfs(int u, int fa, LL mid) {
        for(int i = 1; i <= n; i++) {
            if(a[i] <= a[u] && a[u] <= a[i] + mid) {
                dp[u][i] = 0;
            } else dp[u][i] = inf;
        }
        for(int i = 0; i < e[u].size(); i++) {
            int v = e[u][i];
            if(v == fa) continue;
            dfs(v, u, mid);
            for(int j = 1; j <= n; j++) {
                dp[u][j] += min(dp[v][j], f[v] + 1);
            }
        }
        for(int i = 1; i <= n; i++) {
            f[u] = min(f[u], dp[u][i]);
        }
    }
    
    bool check(LL mid) {
        memset(f, 0x3f, sizeof f);
        dfs(1, 0, mid);
        return f[1] <= k;
    }
    
    void solve() {
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; i++) {
            scanf("%lld", &a[i]);
        }
        for(int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            e[u].push_back(v);
            e[v].push_back(u);
        }
        LL l = 0, r = 2e9;
        LL res = -1;
        while(l <= r) {
            LL mid = l + r >> 1;
    //        printf("mid = %lld
    ", mid);
            if(check(mid)) {
                res = mid;
                r = mid - 1;
            } else l = mid + 1;
        }
        printf("%lld
    ", res);
    }
    
    int main() {
    //    freopen("in.txt", "r", stdin);
        solve();
        return 0;
    }
    
    
  • 相关阅读:
    《MySQL技术内幕》读书笔记
    CentOS裸机环境下安装php-7.3.1
    docker容器和本机互传文件
    一些数组操作函数记录
    window下强制删除文件
    根据一个镜像启动一个容器
    Nginx配置命令大全
    《Linux.Shell编程从入门到精通》读书笔记
    share drive 无效
    vi替换字符串
  • 原文地址:https://www.cnblogs.com/ZX-GO/p/13616323.html
Copyright © 2020-2023  润新知