zoukankan      html  css  js  c++  java
  • [CF1468J] Road Reform

    [CF1468J] Road Reform - 最小生成树

    Description

    给定无向带权图和参数 k,第 i 条边权值为 si,求一棵生成树,并可以对树上边进行修改,每次修改使得边权 +1 或者 -1,使得边权最大值 =k,求最小操作数。

    Solution

    如果所有边权都小于等于 k,好办,选一条最大的,剩下的随便选

    如果存在边权大于等于 k 的,小于 k 的部分中优先选大的(所有小于最大者都可以随便选),大于 k 的部分优先选小的,所以这里的关键是要确定小于 k 的部分中最大的是哪个,好在小于 k 的部分不用计入代价,所以可以先用小于 k 的部分判定连通性,如果已经连通,那么任意选择一条与 k 最接近的即可(不论它是比 k 大还是比 k 小,都不影响结果);如果没有连通,那么从小到大加入若干条大于 k 的,使得图连通即可

    简而言之,先将 <=k 的全部加入,如果连通了,那么从所有边中选择一个与 k 最接近的权值作为答案;如果没有连通,从 >k 的中 Kruskal 一下,和作为答案

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    void solve()
    {
        int n, m, k;
        cin >> n >> m >> k;
        vector<tuple<int, int, int>> edges(m + 2), edges_large, edges_small;
        vector<int> values;
        for (int i = 1; i <= m; i++)
        {
            int a, b, c;
            cin >> a >> b >> c;
            edges[i] = {a, b, c};
            if (c > k)
                edges_large.push_back(edges[i]);
            else
                edges_small.push_back(edges[i]);
            values.push_back(c);
        }
        sort(values.begin(), values.end());
        vector<int> fa(n + 2);
        for (int i = 1; i <= n; i++)
            fa[i] = i;
        function<int(int)> find = [&](int x) -> int {
            return x == fa[x] ? x : fa[x] = find(fa[x]);
        };
        int tot = 1;
        function<void(int, int)> merge = [&](int x, int y) -> void {
            x = find(x);
            y = find(y);
            if (x != y)
                fa[x] = y, tot++;
        };
        for (auto [u, v, w] : edges_small)
            merge(u, v);
        int flag = tot == n;
        if (flag)
        {
            int i = lower_bound(values.begin(), values.end(), k) - values.begin();
            int j = i - 1;
            int ans = 1e18;
            if (i >= 0 && i < m)
                ans = min(ans, abs(k - values[i]));
            if (j >= 0 && j < m)
                ans = min(ans, abs(k - values[j]));
            cout << ans << endl;
        }
        else
        {
            int ans = 0;
            vector<pair<int, pair<int, int>>> ve;
            for (auto [x, y, z] : edges_large)
                ve.push_back({z, {x, y}});
            sort(ve.begin(), ve.end());
            for (int i = 0; i < ve.size(); i++)
            {
                auto [w, pr] = ve[i];
                auto [u, v] = pr;
                if (find(u) != find(v))
                    merge(u, v), ans += w - k;
                if (tot == n)
                    break;
            }
            cout << ans << endl;
        }
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        int t;
        cin >> t;
        while (t--)
        {
            solve();
        }
    }
    
  • 相关阅读:
    Stars in Your Window POJ
    Adding New Machine ZOJ
    洛谷 P3400 仓鼠窝
    django启动时报错:Apps aren't loaded yet.
    netstat命令简单使用
    iostat命令简单使用
    linux下查找指定时间内修改过的或新建的文件
    nginx学习之压缩解压篇(七)
    nginx学习之反向代理篇(六)
    nginx学习之静态内容篇(五)
  • 原文地址:https://www.cnblogs.com/mollnn/p/14399811.html
Copyright © 2011-2022 走看看