代码源自:柳婼 の blog,感谢大神!
解答这一题要同时用到Dijkstra,先求若干条最短路径。然后用dfs在所有的最短路径中找出所求的最佳数据。
哎,对于dfs的回溯部分还是不太熟悉,有些疑问。
哈哈,我快成给柳神写代码注释的了~加油鸭!要自己写代码鸭~
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int inf = 99999999;
int cmax, n, sp, m;
int minNeed = inf, minBack = inf;
int e[510][510], dis[510], weight[510];
bool visit[510];
vector<int> pre[510], path, temppath;二维向量
void dfs(int v) {//对问题站点深度遍历,求minNeed 和 minBack 和path
temppath.push_back(v);
if(v == 0) {/回到了源点,进行所求数据的更新
int need = 0, back = 0;
for(int i = temppath.size() - 1; i >= 0; i--)
{
int id = temppath[i];
if(weight[id] > 0)//比5多
back += weight[id];
else{//比5少
if(back > (0 - weight[id]))//back可以补足当前站点欠缺
back += weight[id];//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 ;
}
for(int i = 0; i < pre[v].size(); i++)
dfs(pre[v][i]);///根据Dijkstra求的最短路径前驱数组,对v的每个前驱进行遍历
temppath.pop_back();///回溯
}
int main() {
fill(e[0], e[0] + 510 * 510, inf);//邻接矩阵填充
fill(dis, dis + 510, inf);///dis用于Dijkstra求最短路径
scanf("%d%d%d%d", &cmax, &n, &sp, &m);///站点的最大容量,站点数,问题站点id,路的条数
for(int i = 1; i <= n; i++) {
scanf("%d", &weight[i]);//各个站点单车数
weight[i] = weight[i] - cmax / 2;//weight当中存站点单车数与perfect相差的绝对值
}
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];//无向带权图的邻接矩阵
}
Dijkstra
dis[0] = 0;//0为源点
for(int i = 0; i <= n; i++) {//n+1次选点
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(visit[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", minBack);
return 0;
}