• [CF715B] Complete The Graph


    [CF715B] Complete The Graph - 最短路,二分

    Description

    给n点m边,L,s,t 修改m条边中边为0的边, 使满足s,t的最短路长度是L

    Solution

    很有意思

    我们知道,每将一条边 +1,最多会使得最短路 L 的长度 +1

    我们构造一个循环 +1 的操作序列,然后在这个操作序列上二分即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    struct Graph
    {
        int n, m;
        vector<vector<pair<int, int>>> g;
        void build(int n_, int m_)
        {
            n = n_;
            m = m_;
            g.resize(n + 2);
        }
    
        void make(int p, int q, int w)
        {
            g[p].push_back({q, w});
            g[q].push_back({p, w});
        }
    
        int dijkstra(int s0, int t0)
        {
            struct Node
            {
                int d, p;
                bool operator<(const Node &rhs) const
                {
                    return d > rhs.d;
                }
            };
    
            priority_queue<Node> que;
            que.push({0, s0});
            vector<int> d(n + 2, 1e18);
            vector<int> v(n + 2, 0);
            d[s0] = 0;
    
            while (que.size())
            {
                auto [dis, p] = que.top();
                que.pop();
                if (v[p])
                    continue;
                v[p] = 1;
                for (auto [q, w] : g[p])
                {
                    if (d[q] > d[p] + w)
                    {
                        d[q] = d[p] + w;
                        que.push({d[q], q});
                    }
                }
            }
    
            return d[t0];
        }
    };
    
    struct Solution
    {
        int n, m, l, s, t;
    
        vector<tuple<int, int, int>> edge_static, edge_dynamic;
    
        void read()
        {
            cin >> n >> m >> l >> s >> t;
            ++s;
            ++t;
            for (int i = 1; i <= m; i++)
            {
                int t1, t2, t3;
                cin >> t1 >> t2 >> t3;
                ++t1;
                ++t2;
                if (t3 == 0)
                    edge_dynamic.push_back({t1, t2, t3});
                else
                    edge_static.push_back({t1, t2, t3});
            }
        }
    
        bool check(int k)
        {
            Graph graph;
            graph.build(n, m);
            if (edge_dynamic.size())
            {
                int a = k / edge_dynamic.size(), b = k % edge_dynamic.size();
                for (int i = 0; i < edge_dynamic.size(); i++)
                {
                    auto [u, v, w] = edge_dynamic[i];
                    if (i < b)
                        graph.make(u, v, w + a + 1);
                    else
                        graph.make(u, v, w + a);
                }
            }
            for (auto [u, v, w] : edge_static)
            {
                graph.make(u, v, w);
            }
            int ans = graph.dijkstra(s, t);
            // cout << "ans=" << ans << " but need " << l << endl;
            if (ans < l)
                return false;
            return true;
        }
    
        bool check_strict(int k)
        {
            Graph graph;
            graph.build(n, m);
            if (edge_dynamic.size())
            {
                int a = k / edge_dynamic.size(), b = k % edge_dynamic.size();
                for (int i = 0; i < edge_dynamic.size(); i++)
                {
                    auto [u, v, w] = edge_dynamic[i];
                    if (i < b)
                        graph.make(u, v, w + a + 1);
                    else
                        graph.make(u, v, w + a);
                }
            }
            for (auto [u, v, w] : edge_static)
            {
                graph.make(u, v, w);
            }
            int ans = graph.dijkstra(s, t);
            // cout << "ans=" << ans << " but need " << l << endl;
            if (ans != l)
                return false;
            return true;
        }
    
        void solve()
        {
            Graph graph;
            graph.build(n, m);
            for (auto [u, v, w] : edge_static)
            {
                graph.make(u, v, w);
            }
            for (auto [u, v, w] : edge_dynamic)
            {
                graph.make(u, v, w);
            }
            if (graph.dijkstra(s, t) > l)
            {
                cout << "NO" << endl;
            }
            else
            {
                int l = edge_dynamic.size(), r = 2e18;
                while (l < r)
                {
                    int mid = (l + r) / 2;
                    if (!check(mid))
                        l = mid + 1;
                    else
                        r = mid;
                }
                if (r > 1e18)
                    cout << "NO" << endl;
    
                else
                {
                    if (check_strict(r) == 0)
                    {
                        cout << "NO" << endl;
                    }
                    else
                    {
                        cout << "YES" << endl;
                        if (edge_dynamic.size())
                        {
                            int k = r;
                            int a = k / edge_dynamic.size(), b = k % edge_dynamic.size();
                            for (int i = 0; i < edge_dynamic.size(); i++)
                            {
                                auto [u, v, w] = edge_dynamic[i];
                                if (i < b)
                                    cout << u - 1 << " " << v - 1 << " " << w + a + 1 << endl;
                                else
                                    cout << u - 1 << " " << v - 1 << " " << w + a << endl;
                            }
                        }
                        for (auto [u, v, w] : edge_static)
                        {
                            cout << u - 1 << " " << v - 1 << " " << w << endl;
                        }
                    }
                }
            }
        }
    };
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        Solution solution;
        solution.read();
        solution.solve();
    }
    
  • 相关阅读:
    C#中的Byte,String,Int,Hex之间的转换函数。
    js继承之原型继承
    node.js module初步理解
    手游热更新方案--Unity3D下的CsToLua技术
    像素迷踪,当Unity的Frame Debugger力不从心时
    Unity内存理解(转)
    Unity5的AssetBundle(二、加载&卸载)
    Sprite Atlas与Sprite Mask详解
    Unity2017新功能Sprite Atlas详解
    Util应用程序框架公共操作类(一):数据类型转换公共操作类(介绍篇)
  • 原文地址:https://www.cnblogs.com/mollnn/p/14453429.html
Copyright © 2020-2023  润新知