1030 Travel Plan(30分)

题目翻译:

给定一幅图,求出发结点到目的结点的最优路径(优先寻找最短路径,若同时存在多条最短路径,则输出花费最小的那条路径)

题解思路:

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值