首页 > 其他 > 详细

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

时间:2021-02-26 19:19:40      阅读:28      评论:0      收藏:0      [点我收藏+]

[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();
}

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

原文:https://www.cnblogs.com/mollnn/p/14453429.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!