洛谷---P4779---【模板】单源最短路径(标准版)---优先队列优化dijkstra

题目背景

2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路。
然后呢?
100 → 60;
Ag → Cu
最终,他因此没能与理想的大学达成契约。
小 F 衷心祝愿大家不再重蹈覆辙。

题目描述

给定一个 个点, 条有向边的带非负权图,请你计算从 出发,到每个点的距离。
数据保证你能从 出发到任意点。

输入格式

第一行为三个正整数 。 第二行起 行,每行三个非负整数 ,表示从 到 有一条权值为 的有向边。

输出格式

输出一行 nn 个空格分隔的非负整数,表示 ss 到每个点的距离。

输入输出样例

输入

4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4

输出

0 2 4 3

思路

用优先队列优化的dijkstra算法,用Node来存每个点,并用vis来记录是否访问,边则用链式前向星来记录。

实现代码

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;

const int maxn = 1e5 + 5;
const int maxm = 2e5 + 5;	
const int Inf = 0x3f3f3f3f;

struct Edge {		//边
	int next,to, val;
	Edge() {}
	Edge(int n, int t, int v): next(n), to(t), val(v) {}
}edge[maxm];

struct Node {		// dijkstra 算法中用于优先队列中的点结构体
	int no, dis;
	Node(int n, int d) : no(n), dis(d) {}
	bool operator < (const Node& other) const { //因为是优先队列,所以重载 <
		return dis > other.dis;
	}
};

int dis[maxn];
int vis[maxn];
int head[maxn];
int cnt = 0;

void link(int u, int v, int w) { // 链式前向星的更新
	edge[++cnt] = Edge(head[u], v, w);
	head[u] = cnt;
}

void dijkstra(int s, int n) { //从 s 点 开始 调用
	priority_queue<Node> q;
	memset(dis, Inf, sizeof(dis));
	memset(vis, 0, sizeof(vis));
	q.push(Node(s, 0));
	while (q.size()) {
		Node top = q.top(); q.pop();
		if (vis[top.no]) continue;
		dis[top.no] = top.dis, vis[top.no] = 1;
		for (int i = head[top.no]; i; i = edge[i].next) {
			int to = edge[i].to, d = edge[i].val;
			if (vis[to]) continue;
			q.push(Node(to, dis[top.no] + d));
		}
	}
	for (int i = 1; i <= n; i++) {
		if (i != 1) cout << " ";
		cout << dis[i];
	}
	cout << endl;
}					

int main() { 
	memset(head, 0., sizeof(head));
	int n, m, s, u, v, w;
	cin >> n >> m >> s;
	for (int i = 1; i <= m; i++) {
		cin >> u >> v >> w;
		link(u, v, w);
	}
	dijkstra(1, n);
	return 0;
}
发布了145 篇原创文章 · 获赞 22 · 访问量 9650

猜你喜欢

转载自blog.csdn.net/weixin_44778155/article/details/104017759