https://www.patest.cn/contests/pat-a-practise/1030
//原来做完Dijkstra加一个DFS是这么加的。要想好怎么递归
//pre[i]存的是到i的之前的所有路径(都是最短路径,从中找出符合条件的)。
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
int n, m, s, d;
int e[510][510], dis[510], cost[510][510];
vector<int> pre[510]; //记录s到d的路径。
bool visit[510];
const int inf = 99999999;
vector<int> path, temppath;
int mincost = inf;
void dfs(int v) {
if(v == s) {
temppath.push_back(v);
int tempcost = 0;
for(int i = temppath.size() - 1; i > 0; i--) {
int id = temppath[i], nextid = temppath[i-1];
tempcost += cost[id][nextid];
}
if(tempcost < mincost) {
mincost = tempcost;
path = temppath;
}
temppath.pop_back();
return ;
}
temppath.push_back(v);
for(int i = 0; i < pre[v].size(); i++) //woc,你读都读不明白,d的size当然是1了。
dfs(pre[v][i]);
temppath.pop_back(); //3是必须要有的,而且能保证1,2循环完就出去。
}
int main() {
fill(e[0], e[0] + 510 * 510, inf);
fill(dis, dis + 510, inf);
scanf("%d%d%d%d", &n, &m, &s, &d);
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];
scanf("%d", &cost[a][b]);
cost[b][a] = cost[a][b];
}
pre[s].push_back(s);
dis[s] = 0;
for(int i = 0; i < n; i++) {
int u = -1, minn = inf;
for(int j = 0; j < n; j++) {
if(visit[j] == false && dis[j] < minn) {
u = j;
minn = 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]) { //原来精髓在此,相等也push进去。而且push的是进去的点,方便往回DFS
pre[v].push_back(u);
}
}
}
}
dfs(d); //做完Dijkstra做DFS,pre记录的是最短的,所以没有0->3这条。
for(int i = path.size() - 1; i >= 0; i--)
printf("%d ", path[i]);
printf("%d %d", dis[d], mincost);
return 0;
}