突然觉得什么都放自己本地不方便
所以还是建了个博客
------------------------------------------------------------------------
以下是代码原文和注释
#include <iostream>
using namespace std;
#define maxv 501 // 题目说车站最多500,加上基地就是501
#define inf 1000000000 //c语言表示的最大整数,1后面9个0
int G[maxv][maxv], d[maxv], pre[maxv], cur_c[maxv], sum[maxv] = {0}; // cur_c表示此时的容量, sum表示到此点的 车辆数
bool vis[maxv];
int main(){
// 准备工作
int c, n, s, m; // c每个站点的最大容量---- n车站的数量----- s出现问题的车站--- m是全部的道路条数
cin >> c >> n >> s >> m;
fill(d, d+n+1, inf); //毕竟0是基地,n不包含0,从1开始算
d[0] = 0;
int pc = c / 2; //pc指的是pefect_cap,一半
// 获取每个车站此时的容量
for (int i = 1; i <= n; i++) cin >> cur_c[i];
//初始化图
for (int i = 0; i < n + 1; i++)
for (int j = 0; j < n + 1; j++)
G[i][j] = inf;
//获取图的路况
for (int i = 0; i < m; i++){
int a, b;
cin >> a, b;
cin >> G[a][b];
G[b][a] = G[a][b]; //无向图
}
//开始所谓的贪心算法
for (int i = 0; i < n+1; i++){
int u = -1, min = inf; // u是临时变量,表示正在拜访的点,min是这些点中,距离上一个点最近的距离
for (int j = 0; j < n; j++){
if (vis[j] == false && d[j] < min){ // 如果此时j没有被拜访过,而且此时他到原点的距离比最小值小,
u = j;
min = d[j];
}
vis[u] = true;
// 以上都是为了找出此时距离原点最近的(还没有拜访过的)点u
for (int v = 0; v < n; v++){ //这里的v是u的邻接点,这个循环是为了调整每个v到原点的最小距离
if (vis[v] == false && G[u][v] != inf){
if (d[u] + G[u][v] < d[v]){ // 如果v到原点的距离,比用u当中介点要小,就调整 d[v]
d[v] = d[u] + G[u][v];
pre[v] = u;
// 正数代表从基地带出去,负数代表带回基地
sum[v] = pc-cur_c[v] + sum[u]; // -----------------*********************可能存在0被算了进去。************
}
else if (d[u] + G[u][v] == d[v]){
int tmp = pc - cur_c[v] + sum[u];
/*
只有三种情况可以替代原来的路径
1.原来带出,之后带出,原来带出多于之后带出
2.原来带回,之后带出(无带回)
3.原来带回,之后带回,之后带回少于原来带回
可以融合为两种可能
*/
if ((sum[v] > 0 && tmp < sum[v]) || (sum[v]<0 && tmp>sum[v])){
pre[v] = u;
sum[v] = tmp;
}
}
}
}
}
}
/*
接下来,判断sum[s]的正负,正的在前面输出,最后输出0; 负的前面输出0,最后输出绝对值
中间的路径根据pre数组倒过来打印就可
*/
return 0;
}