【1030 30 Dijkstra】 Travel Plan

传送门

题意

给定 \(n,m,s,d\) ,表示有 \(n\) 个节点,编号 \(0\sim n-1\)\(m\) 条边,边的距离为 \(distance\) ,花费为 \(cost\) ,求从起点 \(s\) 到终点 \(d\) 的最短路径,距离以及花费,在距离相同时选取花费最小的

数据范围

\(n\leq 500\)

题解

  • Dijkstra ,在更新的时候额外判断相同距离下花费,如果更小则更新
  • 记录每个节点的上个节点 \(pre\) ,通过上个节点得到路径

Code

#include <bits/stdc++.h>
using namespace std;

const int N = 510;

struct Edge {
	int to, dis, cost;
	Edge (int t, int d, int c) : to(t), dis(d), cost(c) {}
};

int n, m, beg, dest;
vector<vector<Edge>> edges(N);
vector<bool> st(N);
vector<int> d(N, INT_MAX), cost(N), pre(N);
void dijkstra() {
	d[beg] = 0;
	for (int i = 0; i < n; i++) {
		int t = -1;
		for (int j = 0; j < n; j++) {
			if (not st[j] and (t == -1 or d[t] > d[j]))
				t = j;
		}
		st[t] = 1;
		for (auto& e : edges[t]) {
			if (d[e.to] > d[t] + e.dis) {
				d[e.to] = d[t] + e.dis;
				cost[e.to] = cost[t] + e.cost;
				pre[e.to] = t;
			} else if(d[e.to] == d[t] + e.dis) {
				if (cost[e.to] > cost[t] + e.cost) {
					cost[e.to] = cost[t] + e.cost;
					pre[e.to] = t;
				}
			}
		}
	}
}	
void dfs(int v) {
	if (v == beg) {
		cout << v << ' ';
		return; 
	}
	dfs(pre[v]);
	cout << v << ' ';
}
int main() {
	cin >> n >> m >> beg >> dest;
	
	while (m--) {
		int u, v, w, c; cin >> u >> v >> w >> c;
		edges[u].push_back(Edge(v, w, c));
		edges[v].push_back(Edge(u, w, c));
	}
	dijkstra();
	dfs(dest);
	cout << d[dest] << ' ' << cost[dest];
}
posted @ 2021-02-18 22:09  Hyx'  阅读(72)  评论(0)    收藏  举报