题目链接:
https://pintia.cn/problem-sets/994805342720868352/problems/994805489282433024
题目分析:
确定到达问题站点的最短路径(用Dijkstra算法),若存在多条最短路径,则选择从中心车站所带车辆最少的路径。
参考代码:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int inf = 99999999;
const int N = 510;
int cmax, n, sp, m; //表示最大存量数,表示车站数, 问题车站编号, 路径车站间的边
int minneed = inf, minremain = inf;
int e[N][N], dis[N], weight[N];
bool vis[N];
vector<int> pre[N], path, temppath;
void dfs(int v){
temppath.push_back(v);
if(v == 0){
int need = 0, remain = 0;
for(int i = temppath.size() - 1; i >= 0; i--){//计算temppath此路径中的minneed, minremain.
int id = temppath[i];
if(weight[id] > 0){
remain += weight[id];
}else{
if(remain > abs(weight[id])){
remain += weight[id];
}else{
need += abs(weight[id]) - remain;
remain = 0;
}
}
}
if(need < minneed){
minneed = need;
minremain = remain;
path = temppath;
}else if(need == minneed && remain < minremain){
minremain = remain;
path = temppath;
}
temppath.pop_back();
return;
}
for(int i = 0; i < pre[v].size(); i++){
dfs(pre[v][i]);
}
temppath.pop_back();
}
int main(){
fill(e[0], e[0] + N*N, inf);
fill(dis, dis + N, inf);
scanf("%d%d%d%d",&cmax, &n, &sp, &m);
for(int i = 1; i <= n; i++){
scanf("%d", &weight[i]);
weight[i] = weight[i] - cmax/2;
}
for(int i = 0; i < m; i++){
int a, b;
scanf("%d %d",&a, &b);
scanf("%d", &e[a][b]);
e[b][a] = e[a][b];
}
dis[0] = 0;
for(int i = 0; i <= n; i++){
int u = -1, minn = inf;
for(int j = 0; j <= n; j++){
if(vis[j] == false && dis[j] < minn){
u = j;
minn = dis[j];
}
}
if(u == -1) break;
vis[u] = true;
for(int v = 0; v <= n; v++){
if(vis[v] == false && e[u][v] != inf){
if(dis[v] > dis[u] + e[u][v]){
dis[v] = dis[u] + e[u][v];
pre[v].clear();
pre[v].push_back(u);
}else if(dis[v] == dis[u] + e[u][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", minremain);
return 0;
}