题目翻译:
给定一幅图,求出发结点到目的结点的最优路径(优先寻找最短路径,若同时存在多条最短路径,则输出花费最小的那条路径)
题解思路:
dfs
代码:
#include<bits/stdc++.h>
using namespace std;
int N, M, S, D;
vector<int> v[510];
int dis[510][510];
int cost[510][510];
int mindis[510];
vector<int> b_path, t_path;
int r_len = INT_MAX, r_cost = INT_MAX;
void dfs(int curcity, int curlen, int curcost)
{
if (curlen > mindis[curcity])return;
else mindis[curcity] = curlen;
t_path.push_back(curcity);
if (curcity == D)
{
if (curlen < r_len)
{
b_path = t_path;
r_len = curlen;
r_cost = curcost;
}
else
{
if (curcost < r_cost)
{
b_path = t_path;
r_cost = curcost;
}
}
}
else
{
for (auto i : v[curcity])
dfs(i, curlen + dis[curcity][i], curcost + cost[curcity][i]);
}
t_path.pop_back();
}
int main()
{
cin >> N >> M >> S >> D;
int p, k, l, c;
for (int i = 0;i < M;i++)
{
cin >> p >> k >> l >> c;
v[p].push_back(k);
v[k].push_back(p);
dis[p][k] = dis[k][p] = l;
cost[p][k] = cost[k][p] = c;
}
for (int i = 0;i < 510;i++)
mindis[i] = INT_MAX;
dfs(S, 0, 0);
for (auto i : b_path)
cout << i << " ";
cout << r_len << " " << r_cost;
}
坑点:
无
二刷:
dfs:
#include<bits/stdc++.h>
using namespace std;
const int N = 510;
const int MAXVAL = 0x3f3f3f3f;
int n, m, s, d;
int dis[N][N], cost[N][N], mindis[N];
vector<int> v[N];
vector<int> path, best_path;
int final_dis=MAXVAL, final_cost=MAXVAL;
void dfs(int curcity, int curlen, int curcost) {
if (curlen > mindis[curcity]) return;
else mindis[curcity] = curlen;
path.push_back(curcity);
if (curcity == d) {
if (curlen < final_dis || (curlen == final_dis && curcost < final_cost)) {
final_dis = curlen;
final_cost = curcost;
best_path = path;
}
}
else {
for (auto i : v[curcity])
dfs(i, curlen + dis[curcity][i], curcost + cost[curcity][i]);
}
path.pop_back();
}
int main() {
cin >> n >> m >> s >> d;
for (int i = 0;i < m;i++) {
int a, b, x, y;cin >> a >> b >> x >> y;
v[a].push_back(b);
v[b].push_back(a);
dis[a][b] = dis[b][a] = x;
cost[a][b] = cost[b][a] = y;
}
memset(mindis, 0x3f, sizeof(mindis));
dfs(s, 0, 0);
for (int i = 0;i < best_path.size();i++) {
if (i != 0) cout << " ";
cout << best_path[i];
}
cout << " " << final_dis << " " << final_cost;
}
dijkstra:
#pragma GCC optimize(2, 3, "Ofast", "inline")
#include<bits/stdc++.h>
using namespace std;
using PII = pair<int, int>;
const int N = 5e2 + 10;
int dis[N], state[N], d[N][N], c[N][N];//d代表距离,c代表花费
int n, m, S, D;
int pre[N]; // 用于存储路径
int total_cost[N]; // 用于记录到每个节点的总花费
//当从起点 S 到某个节点 i 的距离确定后,total_cost[i] 记录从 S 到 i 的最小花费。
vector<int> v[N];//邻接表
void get_path(int start, int end) {
vector<int> path;
for (int cur = end; cur != -1; cur = pre[cur]) {
path.push_back(cur);
}
reverse(path.begin(), path.end());
for (int node : path) {
cout << node << " ";
}
}
// 堆优化Dijkstra求单源最短路径,适合稀疏图
void dijkstra1() {
memset(dis, 0x3f, sizeof(dis));// 将dis初始化为极大值
memset(total_cost, 0x3f, sizeof(total_cost)); // 将花费初始化为极大值
memset(pre, -1, sizeof(pre)); // 初始化前驱节点数组
dis[S] = 0;// 表示起点到自己的距离为0
total_cost[S] = 0; // 起点的花费为0
priority_queue<PII, vector<PII>, greater<PII>> heap;// 必须同时存储距离-结点信息,这样才会根据距离进行排序
heap.push({ 0, S });
while (heap.size()) {
int t = heap.top().second;
heap.pop();
if (state[t]) continue;
state[t] = 1;// 将该点的状态更新为已确认此点到源点的最短距离
for (int j = 0; j < v[t].size(); j++) {// 更新与该点相邻的各点与源点的距离dis
int next = v[t][j];
int new_dist = d[t][next] + dis[t];
int new_cost = c[t][next] + total_cost[t];
if (new_dist < dis[next]) {
dis[next] = new_dist;
total_cost[next] = new_cost;
pre[next] = t; // 记录前驱节点
heap.push({ dis[next], next });
}
else if (new_dist == dis[next]) {
if (new_cost < total_cost[next]) { // 选择花费更小的路径
total_cost[next] = new_cost;
pre[next] = t; // 更新前驱节点
heap.push({ dis[next], next });
}
}
}
}
}
int main() {
cin >> n >> m >> S >> D;
memset(d, 0x3f, sizeof(d));// 将距离数组初始化为极大值
memset(c, 0x3f, sizeof(c));// 将花费数组初始化为极大值
for (int i = 0; i < m; i++) {
int x, y, z, w;
cin >> x >> y >> z >> w;
v[x].push_back(y);
v[y].push_back(x);
d[x][y] = d[y][x] = z;
c[x][y] = c[y][x] = w;
}
dijkstra1();
if (dis[D] != 0x3f3f3f3f) { // 当起点到终点的距离不为极大值,则表示可以从起点走到终点
get_path(S, D);
cout << dis[D] << " " << total_cost[D] << endl; // 输出最短距离和最小花费
}
else {
cout << -1 << endl; // 无法从起点到达终点
}
return 0;
}