[CF1473E] Minimum Path - 分层图最短路

Description

给定一个无向图,定义路径的权值为路径上所有边权的和减去边权的极差。求 1 到其它所有点的最短路。

Solution

很妙的转化:一条边权值变成 0,一条边权值加倍,求最短路

转化后的条件加上最短的条件,就得到了转化前的条件

于是分层图最短路即可

#include <bits/stdc++.h>
using namespace std;

#define int long long 

#define reset(x) memset(x, 0, sizeof x)
#define reset3f(x) memset(x, 0x3f, sizeof x)
namespace sp
{
    const int N = 1e+6 + 5;
    vector<pair<int, int>> g[N];
    int n, v0 = 1, d[N], v[N];
    void make(int t1, int t2, int t3)
    {
        g[t1].push_back(make_pair(t2, t3));
    }
    void reset_graph()
    {
        for (int i = 0; i <= n; i++)
            g[i].clear();
    }
    void solve()
    {
        priority_queue<pair<int, int>> qu;
        reset3f(d);
        reset(v);
        d[v0] = 0;
        qu.push(make_pair(0, v0));
        while (qu.size())
        {
            int p = qu.top().second, r = qu.top().first;
            qu.pop();
            if (r + d[p])
                continue;
            for (int i = 0; i < g[p].size(); i++)
            {
                int q = g[p][i].first, w = g[p][i].second;
                if (d[q] > d[p] + w)
                {
                    d[q] = d[p] + w;
                    qu.push(make_pair(-d[q], q));
                }
            }
        }
    }
} // namespace sp

int n, m, s, t1, t2, t3;

signed main()
{
    cin >> n >> m;
    s = 1;
    int ORIGIND = 0;
    int DOUBLED = n * 2;
    int IGNORED = n;
    int DOUIGND = n * 3;

    for (int i = 1; i <= n; i++)
    {
        sp::make(i, i + n, 0);
        sp::make(i + 2 * n, i + 3 * n, 0);
        sp::make(i, i + 3 * n, 0);
    }

    for (int i = 1; i <= m; i++)
    {
        cin >> t1 >> t2 >> t3;

        sp::make(t1 + ORIGIND, t2 + ORIGIND, t3);
        sp::make(t1 + DOUBLED, t2 + DOUBLED, t3);
        sp::make(t1 + IGNORED, t2 + IGNORED, t3);
        sp::make(t1 + DOUIGND, t2 + DOUIGND, t3);

        sp::make(t1 + ORIGIND, t2 + DOUBLED, t3 * 2);
        sp::make(t1 + IGNORED, t2 + DOUIGND, t3 * 2);

        sp::make(t1 + ORIGIND, t2 + IGNORED, 0);
        sp::make(t1 + DOUBLED, t2 + DOUIGND, 0);

        swap(t1, t2);

        sp::make(t1 + ORIGIND, t2 + ORIGIND, t3);
        sp::make(t1 + DOUBLED, t2 + DOUBLED, t3);
        sp::make(t1 + IGNORED, t2 + IGNORED, t3);
        sp::make(t1 + DOUIGND, t2 + DOUIGND, t3);

        sp::make(t1 + ORIGIND, t2 + DOUBLED, t3 * 2);
        sp::make(t1 + IGNORED, t2 + DOUIGND, t3 * 2);

        sp::make(t1 + ORIGIND, t2 + IGNORED, 0);
        sp::make(t1 + DOUBLED, t2 + DOUIGND, 0);
    }

    sp::solve();

    for (int i = 2; i <= n; i++)
    {
        cout << sp::d[i + DOUIGND] << " ";
    }
}

相关文章: