PAT 1018 Public Bike Management
不会写,看了别人的思路
先用dijstra保存从PBMC(0结点)到sp节点的最短路径,重点是记录最短路径上的前驱节点
因为最短路径可能不止一条,所以一个节点的前驱节点可能不止一个, 所以要用一个vector来为每个节点维护前驱节点
记录前驱节点后,从sp节点开始向0节点进行dfs遍历,当从sp节点遍历到0节点时,找到了一条最短路径,计算这条路径上的need和back,并更新minneed和minback。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int inf = 99999999;
int e[510][510], weight[510], dis[510];
bool visit[510];
int cmax, n, sp, m;
int minneed = inf, minback = inf;
vector<int> pre[510], path, temppath; //dijstra找到的前驱节点可能不唯一,对每个节点v需要一个vector来记录其前驱节点
void dfs(int v) {
temppath.push_back(v);
if (v == 0) {
int back = 0, need = 0;
for (int i = temppath.size() - 1; i >= 0; i--) {
int id = temppath[i];
if (weight[id] > 0) {
back += weight[id];
}
else {
if (back > (0 - weight[id])) {
back += weight[id];
}
else {
need += (0 - weight[id] - back);
back = 0;
}
}
}
if (need < minneed) {
minneed = need;
minback = back;
path = temppath;
}
else if (need == minneed && back < minback) {
minback = back;
path = temppath;
}
temppath.pop_back();
return;
}
else {
for (int i = 0; i < pre[v].size(); i++) {
dfs(pre[v][i]); //每个节点要循环搜寻其前驱节点,因为它可能不唯一
}
temppath.pop_back();
}
}
int main() {
fill(e[0], e[0] + 510 * 510, inf);
fill(dis, dis + 510, inf);
fill(visit, visit + 510, false);
cin >> cmax >> n >> sp >> m;
for (int i = 1; i <= n; i++) {
cin >> weight[i];
weight[i] -= cmax / 2;
}
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
e[a][b] = e[b][a] = c;
}
dis[0] = 0;
for (int i = 0; i <= n; i++) {
int u = -1, minn = inf;
for (int j = 0; j <= n; j++) {
if (visit[j] == false && dis[j] < minn) {
u = j;
minn = dis[j];
}
}
if (u == -1) break;
visit[u] = true;
for (int v = 0; v <= n; v++) {
if (dis[u] + e[u][v] < dis[v]) {
dis[v] = dis[u] + e[u][v];
pre[v].clear();
pre[v].push_back(u);
}
else if (dis[u] + e[u][v] == dis[v]) {
pre[v].push_back(u);
}
}
}
dfs(sp);
printf("%d 0", minneed);
for (int i = path.size() - 2; i >= 0; i--) {
printf("->%d", path[i]);
}
printf(" %d", minback);
return 0;
}