zoukankan      html  css  js  c++  java
  • [ICPC2019上海H] Tree Partition

    [ICPC2019上海H] Tree Partition - 二分,贪心

    Description

    给定一颗 n 个节点的树,每个点带点权,让你分成 k 份,使得连通块中最大的点权和最小,输出这个最小值

    Solution

    二分答案转化为判定问题,会有一个组内和上限 mid,我们 DFS 整棵树,每个子树在内部划分,剩下来的一点返回给父亲让父亲处理

    父亲将所有孩子传给他的剩余量中,挑出较小的几个加到自己身上(留着待会向上传),保证这部分的和不超过 mid,其它的,只能一人分配一个新组

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    const int N = 2e5 + 5;
    
    void clear(int *a, int n)
    {
        for (int i = 0; i <= n; i++)
            a[i] = 0;
    }
    
    int n, k;
    vector<int> g[N];
    int w[N];
    int ans, lim;
    
    int dfs(int p, int from)
    {
        int sum = w[p];
        vector<int> vec;
        for (int q : g[p])
        {
            if (q == from)
                continue;
            int res = dfs(q, p);
            vec.push_back(res);
            if (res > lim)
            {
                ans = 1e9;
            }
        }
        sort(vec.begin(), vec.end());
        int c = 0;
        for (int i = 0; i < vec.size(); i++)
            if (sum + vec[i] <= lim)
                sum += vec[i], ++c;
        ans += vec.size() - c;
        return sum;
    }
    
    bool check(int mid)
    {
        ans = 0;
        lim = mid;
        int res = dfs(1, 0);
        if (res > 0)
            ++ans;
        if (res > lim)
            return false;
        return ans <= k;
    }
    
    void solve()
    {
        cin >> n >> k;
        for (int i = 1; i <= n; i++)
            g[i].clear();
        for (int i = 1; i < n; i++)
        {
            int u, v;
            cin >> u >> v;
            g[u].push_back(v);
            g[v].push_back(u);
        }
        for (int i = 1; i <= n; i++)
            cin >> w[i];
    
        int l = 1, r = 1e18;
        while (l < r)
        {
            int mid = (l + r) / 2;
            if (check(mid))
                r = mid;
            else
                l = mid + 1;
        }
        cout << l << endl;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        int t;
        cin >> t;
        for (int i = 1; i <= t; i++)
        {
            cout << "Case #" << i << ": ";
            solve();
        }
    }
    
  • 相关阅读:
    Python函数式编程(一):高级函数
    Python高级特性:列表生成式
    Python高级特性:迭代
    Python高级特性:切片
    Python学习笔记
    关于相机拍照获取图片onActivityResult返回data 为null的问题
    191019
    状语和状语从句
    191018
    191017
  • 原文地址:https://www.cnblogs.com/mollnn/p/14571250.html
Copyright © 2011-2022 走看看