[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] << " ";
}
}