传送门
如果只求第 1 1 1个点分别到第 i i i个点的最小值,那么直接跑个 d i j dij dij,但是本题加了路径上分别要减去最大值和加上最小值,那么考虑 d [ i ] [ 0 / 1 ] [ 0 / 1 ] d[i][0/1][0/1] d[i][0/1][0/1]分别表示为从第 1 1 1个点到第 i i i个点没减去最大值/已经减去最大值和没减去最小值/已经减去最小值的最小路径,那么最后答案必然是各个 d [ i ] [ 1 ] [ 1 ] d[i][1][1] d[i][1][1],最后分析一波
d [ v ] [ 0 ] [ 0 ] = m i n ( d [ u ] [ 0 ] [ 0 ] + w , d [ v ] [ 0 ] [ 0 ] ) d [ v ] [ 1 ] [ 0 ] = m i n ( d [ u ] [ 0 ] [ 0 ] , d [ v ] [ 1 ] [ 0 ] ) d [ v ] [ 1 ] [ 0 ] = m i n ( d [ u ] [ 1 ] [ 0 ] + w , d [ v ] [ 1 ] [ 0 ] d [ v ] [ 0 ] [ 1 ] = m i n ( d [ u ] [ 0 ] [ 0 ] + 2 ∗ w , d [ v ] [ 0 ] [ 1 ] ) d [ v ] [ 0 ] [ 1 ] = m i n ( d [ u ] [ 0 ] [ 1 ] + w , d [ v ] [ 0 ] [ 1 ] ) d [ v ] [ 1 ] [ 1 ] = m i n ( d [ u ] [ 0 ] [ 0 ] + w , d [ v ] [ 1 ] [ 1 ] ) d [ v ] [ 1 ] [ 1 ] = m i n ( d [ u ] [ 1 ] [ 0 ] + 2 ∗ w , d [ v ] [ 1 ] [ 1 ] ) d [ v ] [ 1 ] [ 1 ] = m i n ( d [ u ] [ 0 ] [ 1 ] , d [ 1 ] [ 1 ] [ 1 ] ) d [ v ] [ 1 ] [ 1 ] = m i n ( d [ u ] [ 1 ] [ 1 ] + w , d [ v ] [ 1 ] [ 1 ] ) d[v][0][0]=min(d[u][0][0]+w,d[v][0][0])\\ d[v][1][0]=min(d[u][0][0],d[v][1][0])\\ d[v][1][0]=min(d[u][1][0]+w,d[v][1][0]\\ d[v][0][1]=min(d[u][0][0]+2*w,d[v][0][1])\\ d[v][0][1]=min(d[u][0][1]+w,d[v][0][1])\\ d[v][1][1]=min(d[u][0][0]+w,d[v][1][1])\\ d[v][1][1]=min(d[u][1][0]+2*w,d[v][1][1])\\ d[v][1][1]=min(d[u][0][1],d[1][1][1])\\ d[v][1][1]=min(d[u][1][1]+w,d[v][1][1]) d[v][0][0]=min(d[u][0][0]+w,d[v][0][0])d[v][1][0]=min(d[u][0][0],d[v][1][0])d[v][1][0]=min(d[u][1][0]+w,d[v][1][0]d[v][0][1]=min(d[u][0][0]+2∗w,d[v][0][1])d[v][0][1]=min(d[u][0][1]+w,d[v][0][1])d[v][1][1]=min(d[u][0][0]+w,d[v][1][1])d[v][1][1]=min(d[u][1][0]+2∗w,d[v][1][1])d[v][1][1]=min(d[u][0][1],d[1][1][1])d[v][1][1]=min(d[u][1][1]+w,d[v][1][1])
然后就是不断地跑spfa更新即可(参考官方题解)
准备改改代码规范了,该空格就得空格呢,毕竟代码是给别人看的
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, m, u, v, w;
long long d[N][2][2];
vector<pair<int, int>> g[N];
int main()
{
cin >> n >> m;
for (int i = 0; i < m; i++) {
cin >> u >> v >> w;
u--; v--;
g[u].emplace_back(v, w);
g[v].emplace_back(u, w);
}
for (int i = 0; i < n; i++) {
for(int j = 0; j < 2; j++) {
for(int k = 0; k < 2; k++) {
d[i][j][k] = (long long)1e18;
}
}
}
d[0][0][0] = 0;
set<pair<long long, array<int, 3>>> q;
q.insert({
0, {
0, 0, 0}});
while (!q.empty()) {
auto [u, mx, mn] = q.begin()->second;
q.erase(q.begin());
for (auto [v, w] : g[u]) {
for (int i = 0; i <= 1 - mx; i++) {
for (int j = 0; j <= 1 - mn; j++) {
if (d[v][i | mx][j | mn] > d[u][mx][mn] + (1 - i + j) * w) {
auto it = q.find({
d[v][i | mx][j | mn], {
v, i | mx, j | mn}});
if (it != q.end()) {
q.erase(it);
}
d[v][i | mx][j | mn] = d[u][mx][mn] + (1 - i + j) * w;
q.insert({
d[v][i | mx][j | mn], {
v, i | mx, j | mn}});
}
}
}
}
}
for (int i = 1; i < n; i++) {
cout << d[i][1][1] << " ";
}
return 0;
}