测试用例:
10 2 2 2
2 10
0 1 1
1 2 1
3 0->1->2 5
10 3 3 3
11 0 10
0 1 1
1 2 1
2 3 1
0 0->1->2->3 6
10 4 4 5
6 7 5 0
0 1 1
0 2 1
1 3 1
2 3 1
3 4 1
3 0->2->3->4 0
10 4 4 4
6 0 11 0
0 1 1
1 2 1
2 3 1
3 4 1
4 0->1->2->3->4 1
10 4 4 8
0 11 3 0
0 1 2
0 2 3
0 3 2
1 2 1
2 3 1
1 4 2
2 4 1
3 4 2
0 0->2->4 1
10 6 6 8
8 9 4 6 7 2
0 1 1
0 2 1
1 3 1
2 3 1
3 4 1
3 5 2
4 6 1
5 6 1
0 0->1->3->4->6 0
- 出发的时候,一边走要一边平衡路上的车数量,也就是,例如先遇到一个需要2个的自行车摊,再遇到一个多出3个的自行车摊,还是需要从出发点携带2个自行车,否则,遇到第一个需要的自行车摊时,无法平衡;后面遇到的这个多出3个的自行车摊,如果没有被消耗掉,那还要带回到自行车中心。后面多出来的这3个,是无法弥补到前面缺乏自行车的地方的。一次路过,路上的自行车数都要平衡
- 可以先保存pre路径,然后再dfs来遍历,达到查找等长,多条件判断路径的目的
#include <iostream>
#include<vector>
#include<algorithm>
#include<assert.h>
using namespace std;
#define INF 0x3FFFFFFF
void dfs(vector<int>* pre, int start, int end, vector<int>* stationBikes, vector<int>* path);
struct Path {
int end;
int length;
Path(int end, int length) :end(end), length(length) {}
};
void Print(int length, bool* array) {
for (int i = 0; i < length; i++)
{
cout << array[i] << " ";
}
cout << endl;
}
int minNeed = INF, minRemain = INF;
vector<int> pathSave;
void Dijtra(int stationNum, int problemIndex, vector<int>* stationBikes, vector<Path>* graph) {
bool* visited = new bool[stationNum]; // 保存是否访问过
vector<int>* pre = new vector<int>[stationNum]; // 保存每个站点的前序节点
int* pathLength = new int[stationNum]; // 保存0到每个站点的路径长度
for (int i = 0; i < stationNum; i++)
{
visited[i] = false;
pre[i].clear();
pathLength[i] = INF;
}
visited[0] = true;
pathLength[0] = 0;
bool hasUnvisited = true;
for (int i = 0; i < graph[0].size(); i++)
{
pre[graph[0][i].end].push_back(0);
pathLength[graph[0][i].end] = graph[0][i].length;
}
while (hasUnvisited) {
hasUnvisited = false;
int NextNode = 0, min = INF;
// 对所有节点,找未访问过的最小路径点
for (int i = 1; i < stationNum; i++)
{
if (visited[i] == false && pathLength[i] < min)
{
min = pathLength[i];
NextNode = i;
hasUnvisited = true;
}
}
if (hasUnvisited == false || visited[problemIndex] == true)
{
// 剩余节点不连通或者全部节点已访问,
// 或者 有问题的那个节点已经被访问了
break;
}
vector<Path> paths = graph[NextNode];
visited[NextNode] = true;
for (int i = 0; i < paths.size(); i++)
{
if (visited[paths[i].end] == false && paths[i].length < INF)
{
if (paths[i].length + pathLength[NextNode] < pathLength[paths[i].end])
{
// 起点的最短路径+当前路径长< 之前的终点的长,更新最短路径
pathLength[paths[i].end] = paths[i].length + pathLength[NextNode];
pre[paths[i].end].clear();
pre[paths[i].end].push_back(NextNode);
}
else if (paths[i].length + pathLength[NextNode] == pathLength[paths[i].end])
{
pre[paths[i].end].push_back(NextNode);
}
}
}
}
//打印一下路径前序
/*
for (int i = 0; i < stationNum; i++)
{
cout << i << ": ";
for (auto c : pre[i]) {
cout << c << " ";
}
cout << endl;
}*/
vector<int> path;
dfs(pre, 0, problemIndex, stationBikes, &path);
cout << minNeed<<" ";
for (int i = pathSave.size()-1; i >=0; i--)
{
cout << pathSave[i];
if (i>=1)
{
cout << "->";
}
}
cout <<" " << minRemain;
}
void dfs(vector<int>* pre, int start, int end, vector<int>* stationBikes, vector<int>* path) {
if (end==0)
{
path->push_back(end);
// 叶子节点:
int need = 0, remain = 0;
for (int i = path->size()-1; i >=0; i--)
{
int id = (*path)[i];
if ((*stationBikes)[id]>0)
{
remain += (*stationBikes)[id];
}
else {
if (remain>abs((*stationBikes)[id]))
{
remain-=abs((*stationBikes)[id]);
}
else {
need+=abs((*stationBikes)[id])-remain;
remain = 0;
}
}
}
if (need<minNeed)
{
minNeed = need;
minRemain = remain;
pathSave = *path;
}
else if (need == minNeed && remain<minRemain) {
minRemain = remain;
pathSave = *path;
}
(*path).pop_back();
return;
}
(*path).push_back(end);
vector<int> pathEnd = pre[end];
for (int i = 0; i < pathEnd.size(); i++)
{
dfs(pre,start, pathEnd[i],stationBikes,path);
}
(*path).pop_back();
}
int main()
{
int capicity, stationNum, problemIndex, paths;
cin >> capicity >> stationNum >> problemIndex >> paths;
int leftNum;
vector<int> stationBikes;
stationBikes.push_back(0);
for (int i = 0; i < stationNum; i++)
{
cin >> leftNum;
stationBikes.push_back(leftNum-capicity/2);
}
int aim, end, length;
vector<Path>* graph = new vector<Path>[stationNum + 1];
for (int i = 0; i < paths; i++)
{
cin >> aim >> end >> length;
graph[aim].push_back(Path(end, length));
graph[end].push_back(Path(aim, length));
}
Dijtra( stationNum + 1, problemIndex, &stationBikes, graph);
}