传送门
如果只求第
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;
}
&spm=1001.2101.3001.5002&articleId=112733814&d=1&t=3&u=99fa7af35d794a519b6a526d2067195c)
332

被折叠的 条评论
为什么被折叠?



