每个车站的最大容量为一个偶数$C_{max}$,如果车站中自行车的数量为$C_{max}/2$,则认为该车站处于完美状态
,如果有一个车站自行车数量为 0 或者为$C_{max}$,则认为该车站有问题,从控制中心 PBMC 出发携带一定数量的自行车前往该车站,并在路上收集一些自行车,使得沿途的车站以及最终到达的问题车站达到完美状态
,求出从 PBMC 到达该问题车站的最短路径,如果有多条,选择需要从 PBMC 携带自行车数量最少的路径;如果仍有多条,选择从问题车站带回自行车最少的。
输入第一行包含 4 个数字:$C_{max},N,S_p,M$,其中,$C_{max}$始终是偶数,是每个站点的最大容量;N 表示总站数;$S_p$表示问题站点的索引(站点从 1 到 N 编号,PBMC 用顶点 0 表示);M 表示道路数。第二行包含 N 个非负数$C_i$,表示站点$i$的实际容量。接下来 M 行,每行包含 3 个数字:$S_i,S_j,T_{ij}$,表示$S_i$和$S_j$之间有一条距离为
将结果打印在一行中。首先输出 PBMC 必须发送的自行车数量。然后,在空格之后,以$0->S_1->\cdots->S_p$的格式输出路径。最后输出该路径返回 PBMC 的自行车数量。请注意,如果这样的路径不是唯一的,请输出需要返回 PBMC 的自行车数量最少的路径。题目保证这样的路径是唯一的。
利用 Dijkstra 算法求出所有距离最短的路径,并在从问题车站回溯到 PBMC 的 DFS 中选择符合要求的唯一的最短路径。为了编码方便,不妨在读入每个车站的自行车数量时都减去$C_{max}/2$,如果仍为正表示该车站需要带回自行车,如果为负表示该车站需要从 PBMC 获取自行车。具体实现可见代码。
- 在选择路径时有三种选择条件,且优先级逐条递减:
- 距离最短
- 从 PBMC 携带自行车数量最少
- 从问题车站带回自行车数量最少
- 需要使得沿途所有车站都达到
完美状态
,而不仅是问题车站 - 不能在 Dijkstra 中直接选择出唯一的路径,因为从 PBMC 携带自行车数量以及从问题车站带回自行车数量在路径上的传递不是简单的相加过程。只有当所有路径都确定后才能去选择最符合条件的那条路径
#include <bits/stdc++.h>
using namespace std;
using gg = long long;
const gg MAX = 505;
using agg2 = array<gg, 2>;
struct Edge {
gg to, cost;
Edge(gg t, gg c) : to(t), cost(c) {}
};
vector<vector<Edge>> graph(MAX);
vector<gg> dis(MAX, INT_MAX), w(MAX), path, tempPath;
vector<vector<gg>> past(MAX);
gg sent = INT_MAX, collect = INT_MAX;
void Dijkstra(gg s) {
priority_queue<agg2, vector<agg2>, greater<agg2>> pq;
dis[s] = 0;
pq.push({0, s});
while (!pq.empty()) {
auto p = pq.top();
pq.pop();
if (dis[p[1]] != p[0]) {
continue;
}
for (auto& e : graph[p[1]]) {
if (dis[e.to] > p[0] + e.cost) {
dis[e.to] = p[0] + e.cost;
past[e.to].clear();
past[e.to].push_back(p[1]);
pq.push({dis[e.to], e.to});
} else if (dis[e.to] == p[0] + e.cost) {
past[e.to].push_back(p[1]);
}
}
}
}
void dfs(gg v) {
if (v == 0) {
gg curSent = 0, curCollect = 0;
for (auto i = tempPath.rbegin(); i != tempPath.rend(); ++i) {
if (w[*i] >= 0) {
curCollect += w[*i];
} else if (curCollect >= abs(w[*i])) {
curCollect += w[*i];
} else {
curSent -= curCollect + (w[*i]);
curCollect = 0;
}
}
tempPath.push_back(v);
if (tie(curSent, curCollect) < tie(sent, collect)) {
sent = curSent;
collect = curCollect;
path = tempPath;
}
tempPath.pop_back();
return;
}
tempPath.push_back(v);
for (gg i : past[v]) {
dfs(i);
}
tempPath.pop_back();
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
gg ci, ni, si, mi;
cin >> ci >> ni >> si >> mi;
ci /= 2;
for (gg i = 1; i <= ni; ++i) {
cin >> w[i];
w[i] -= ci;
}
while (mi--) {
gg ai, bi, ci;
cin >> ai >> bi >> ci;
graph[ai].push_back(Edge(bi, ci));
graph[bi].push_back(Edge(ai, ci));
}
Dijkstra(0);
dfs(si);
cout << sent << " ";
for (auto i = path.rbegin(); i != path.rend(); ++i) {
cout << (i == path.rbegin() ? "" : "->") << *i;
}
cout << " " << collect;
return 0;
}