PAT A1030 Travel Plan
思路:根据Dijkstra算法求出最短路径,用pre保存路径上每个结点的前驱。再使用DFS从终点进行倒序遍历,记录下最小的cost即为答案路径。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN = 505;
const int INF =1e9;
int N, M, S, ed, minCost = INF;
int G[MAXN][MAXN], cost[MAXN][MAXN], d[MAXN];
bool visit[MAXN];
vector<int> pre[MAXN], temp, ans;
void Dijkstra(int s) {
fill(d, d + MAXN, INF);
d[s] = 0;
for(int i = 0; i < N - 1; i++) {
int u = -1, MIN = INF;
for(int j = 0; j < N; j++)
if(!visit[j] && d[j] < MIN) {
u = j;
MIN = d[j];
}
if(u == -1) return;
visit[u] = true;
for(int v = 0; v < N; v++)
if(!visit[v] && G[u][v] < INF) {
if(d[u] + G[u][v] < d[v]) {
d[v] = d[u] + G[u][v];
pre[v].clear();
pre[v].push_back(u);
} else if(d[u] + G[u][v] == d[v]) {
pre[v].push_back(u);
}
}
}
}
void DFS(int v) {
if(v == S) {
temp.push_back(v);
int nowCost = 0;
for(int i = temp.size() - 1; i > 0; i--) {
int id = temp[i], id_next = temp[i - 1];
nowCost += cost[id][id_next];
}
if(nowCost < minCost) {
minCost = nowCost;
ans = temp;
}
temp.pop_back();
return;
}
temp.push_back(v);
for(int i = 0; i < pre[v].size(); i++)
DFS(pre[v][i]);
temp.pop_back();
}
int main() {
cin >> N >> M >> S >> ed;
int u, v, dist, c;
fill(G[0], G[0] + MAXN * MAXN, INF);
for(int i = 0; i < M; i++) {
cin >> u >> v >> dist >> c;
G[u][v] = G[v][u] = dist;
cost[u][v] = cost[v][u] = c;
}
Dijkstra(S);
DFS(ed);
for(int i = ans.size() - 1; i >= 0; i--)
printf("%d ", ans[i]);
printf("%d %d\n", d[ed], minCost);
return 0;
}