返回题解分享
讨论 / 题解分享/ 帖子详情

出差(编程题) - 题解

堆优化 迪加斯特拉算法

#include <cstdio>
#include <vector>
#include <queue>
#include <tuple>

using namespace std;

int main() {
	const int INF = 1e9;
	int n, m;
	scanf("%d %d", &n, &m);
	vector<int> dian(n);
	vector<vector<tuple<int, int>>> G(n); // [u] -> <v, w>
	for (int i = 0; i < n; ++i)
		scanf("%d", &dian[i]);
		
	for (int i = 0, u, v, w; i < m; ++i) {
		scanf("%d %d %d", &u, &v, &w);
		--u, --v;
		G[u].push_back(make_tuple(v, w + dian[v]));
		G[v].push_back(make_tuple(u, w + dian[u]));
	}
	
	// [L, 点]
	priority_queue<tuple<int, int>, vector<tuple<int, int>>, greater<tuple<int, int>>> pq;
	vector<int> dis(n, INF);
	dis[0] = 0;
	pq.push(make_tuple(0, 0));
	while (pq.size()) {
		int d, x;
		tie(d, x) = pq.top();
		pq.pop();
		
		if (d > dis[x]) {
			if (x == n - 1)
				break;
			continue;
		}
		
		for (auto& it : G[x]) {
			int dx = d + get<1>(it);
			if (dx < dis[get<0>(it)]) {
				dis[get<0>(it)] = dx;
				pq.push(make_tuple(dx, get<0>(it)));
			}
		}
	}
	
	printf("%d\n", dis[n - 1] - dian[n - 1]);
	return 0;
}
1 回复 0 转发 1 喜欢 5 阅读
回复 (1)
默认 最新
露米 13 小时前
看到你分享的题解了,代码写得很整洁。

把点的权重转化到边权上的思路很清晰,这样处理起来确实方便很多。最后输出时减去终点权重的那个小细节,你也考虑到了,真的很细心。

在实现的过程中,有没有遇到什么让你觉得比较微妙的地方,或者需要特别注意的边界情况呀?🙂
比如关于起点权重的初始处理,或者是处理这类带点权的最短路问题时的一些心得。

期待以后能看到你更多的分享,如果练习中遇到卡壳的地方,也可以随时发出来,我们一起讨论。加油~
0