这题真的是个好题目啊,基本涵盖了Dijkstral的所有考点。
静下心来写了一个小时,发现测试点5、7过不了,自己分析了一会无果,参考了别人的博客,发现这两点是个坑,因为沿路后面的自行车无法填补前面自行车缺少的,而前面自行车多出来的可以填补后面缺少的。
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int INF = 1e9;
const int MAXV = 510;
int d[MAXV];
int num[MAXV];
int G[MAXV][MAXV];
int half;
int tb = INF;
int mn = INF;
int out = 0;
int in = 0;
int c, n, p, m;
bool vis[MAXV] = {false};
vector<int> pre[MAXV], tempPath, path;
void Dijkstral(int s){
fill(d, d+MAXV, INF);
d[s] = 0;
for(int i=0; i<=n; i++){
int u = -1, MIN = INF;
for(int j=0; j<=n; j++){
if(vis[j]==false && d[j]<MIN){
u = j;
MIN = d[j];
}
}
if(u == -1) return;
vis[u] = true;
for(int v=0; v<=n; v++){
if(vis[v]==false && G[u][v]!=INF){
if(d[v] > d[u] + G[u][v]){
d[v] = d[u] + G[u][v];
pre[v].clear();
pre[v].push_back(u);
}else if(d[v] == d[u] + G[u][v]){
pre[v].push_back(u);
}
}
}
}
}
void DFS(int e){
if(e == 0){
tempPath.push_back(e);
int need = 0;
int back = 0;
for(int i=0; i<tempPath.size()-1; i++){
int index = tempPath[i];
if(num[index] > half){
back += (num[index]-half);
if(need != 0){
if(back <= need){
need -= back;
back = 0;
}else{
back -= need;
need = 0;
}
}
}else if(num[index] < half){
need += (half-num[index]);
}
}
if(need < mn){
tb = back;
path = tempPath;
in = tb;
mn = need;
out = need;
}else if(need == mn){
if(back < tb){
tb = back;
path = tempPath;
in = tb;
mn = need;
out = need;
}
}
tempPath.pop_back();
}
tempPath.push_back(e);
for(int i=0; i<pre[e].size(); i++){
DFS(pre[e][i]);
}
tempPath.pop_back();
}
int main(){
fill(G[0], G[0]+MAXV*MAXV, INF);
int u, v, w;
scanf("%d %d %d %d", &c, &n, &p, &m);
for(int i=1; i<=n; i++){
scanf("%d", &num[i]);
}
half = c/2;
for(int i=0; i<m; i++){
scanf("%d %d %d", &u, &v, &w);
G[u][v] = w;
G[v][u] = w;
}
Dijkstral(0);
DFS(p);
printf("%d ", out);
for(int i=path.size()-1; i>=0; i--){
printf("%d", path[i]);
if(i != 0) printf("->");
}
printf(" %d", in);
return 0;
}