Dijistra寻找最短路径+DFS还原路径,并二次处理得到最佳答案。
附本人AC代码:
#include<iostream>
#include<vector>
using namespace std;
const int inf = 100000000;
int cap, N, S, M, t1, t2, len;
vector<int>aval, tmp, val;
int map[510][510], dis[510];
bool flag[510];
vector<vector<int>>ans, fans;
void findpath(int x) {
if (x == 0) {
fans.push_back(tmp);
return;
}
tmp.push_back(x);
for (int i = 0; i < ans[x].size(); i++) {
findpath(ans[x][i]);
}
tmp.pop_back();
}
int main() {
fill(map[0], map[0] + 510 * 510, inf);
fill(dis, dis + 510, inf);
scanf("%d%d%d%d", &cap, &N, &S, &M);
ans.resize(N+1);
aval.resize(N + 1);
for (int i = 1; i <=N; i++) {
scanf("%d", &len);
aval[i] = len - cap / 2;
}
for (int i = 0; i < M; i++) {
scanf("%d%d%d", &t1, &t2, &len);
map[t2][t1]=map[t1][t2] = len;
}
dis[0] = 0;
for (int i = 0; i <=N; i++) {
int index = -1, mini = inf;
for (int i = 0; i <= N; i++) {
if (flag[i] == false && dis[i] < mini) {
index = i;
mini = dis[i];
}
}
if (index == -1)break;
flag[index] = true;
for (int j = 1; j <= N; j++) {
if (map[index][j] != inf) {
if (dis[index] + map[index][j] < dis[j]) {
ans[j].clear();
ans[j].push_back(index);
dis[j] = dis[index] + map[index][j];
}
else if (dis[j] == dis[index] + map[index][j]) {
ans[j].push_back(index);
}
}
}
}
findpath(S);
int mintake = 999999, minback = 9999999;
for (int i = 0; i < fans.size(); i++) {
int take = 0, back = 0;
for (int j = fans[i].size() - 1; j >= 0; j--) {
if (aval[fans[i][j]] < 0) {
if (back + aval[fans[i][j]] >= 0) {//够用
back += aval[fans[i][j]];
}
else {
take += (back + aval[fans[i][j]])*-1;
back = 0;
}
}
else back += aval[fans[i][j]];
}
if (take < mintake) {
mintake = take;
val = fans[i];
minback = back;
}
else if (take == mintake) {
if (back < minback) {
val = fans[i];
minback = back;
}
}
}
printf("%d 0", mintake);
for (int i = val.size() - 1; i >= 0; i--) {
printf("->%d", val[i]);
}
printf(" %d", minback);
return 0;
}