每日一题 第二期 洛谷 最短路径

【模板】单源最短路径(标准版)

题目链接

题目背景

2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路。

然后呢?

100 → 60 100 \rightarrow 60 100→60;

Ag → Cu \text{Ag} \rightarrow \text{Cu} Ag→Cu;

最终,他因此没能与理想的大学达成契约。

小 F 衷心祝愿大家不再重蹈覆辙。

题目描述

给定一个 n n n 个点, m m m 条有向边的带非负权图,请你计算从 s s s 出发,到每个点的距离。

数据保证你能从 s s s 出发到任意点。

输入格式

第一行为三个正整数 n , m , s n, m, s n,m,s。

第二行起 m m m 行,每行三个非负整数 u i , v i , w i u_i, v_i, w_i ui,vi,wi,表示从 u i u_i ui 到 v i v_i vi 有一条权值为 w i w_i wi 的有向边。

输出格式

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

样例 #1

样例输入 #1

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

样例输出 #1

0 2 4 3

提示

样例解释请参考 数据随机的模板题

1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1≤n≤105;

1 ≤ m ≤ 2 × 1 0 5 1 \leq m \leq 2\times 10^5 1≤m≤2×105;

s = 1 s = 1 s=1;

1 ≤ u i , v i ≤ n 1 \leq u_i, v_i\leq n 1≤ui,vi≤n;

0 ≤ w i ≤ 1 0 9 0 \leq w_i \leq 10 ^ 9 0≤wi≤109,

0 ≤ ∑ w i ≤ 1 0 9 0 \leq \sum w_i \leq 10 ^ 9 0≤∑wi≤109。

本题数据可能会持续更新,但不会重测,望周知。

2018.09.04 数据更新 from @zzq

思路:本题考察最短路,与本人之前写过的文章相符

链接最短路问题

堆优化版的Dijkstra

AC代码:

cpp 复制代码
#include<map>
#include<set>
#include<stack>
#include<cmath>
#include<queue>
#include<string>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<numeric>
#define endl '\n'
using namespace std;

typedef long long ll;
typedef pair<int, int>PII;
const int N=3e5+10;
const int MOD=998244353;
const int INF=0X3F3F3F3F;
const int dx[]={-1,1,0,0,-1,-1,+1,+1};
const int dy[]={0,0,-1,1,-1,+1,-1,+1};
const int M = 1e4 + 10;

int n, m, s;
int h[N], idx, e[N], ne[N], w[N];
int dis[N];
int st[N];

void add(int a, int b, int c)
{
	e[idx] = b, w[idx] =  c, ne[idx] = h[a], h[a] = idx ++;
}

void dist()
{
	memset(dis, 0x3f, sizeof dis);
	dis[s] = 0;
	priority_queue<PII, vector<PII>, greater<PII>>heap;
	heap.push({0, s});
	while(heap.size()){
		auto t = heap.top();
		heap.pop();
		int ver = t.second ;
		if(st[ver]) continue;
		st[ver] = 1;
		for(int i = h[ver]; i != -1; i = ne[i])
		{
			int j = e[i];
			if(dis[j] > w[i] + dis[ver] && !st[j])
			{
				dis[j] = w[i] + dis[ver];
				heap.push({dis[j], j});
			}
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	memset(h, - 1, sizeof h);
	cin >> n >> m >> s;
	for(int i = 1; i <= m; i ++)
	{
		int a, b, c;

		
		cin >> a >> b >> c;
		add(a, b, c);
	}
	dist();
	for(int i = 1; i <= n; i ++)
	{
		cout << dis[i] << " ";
	}
	cout << endl;
	return 0;
}
相关推荐
sewinger13 分钟前
区间合并算法详解
算法
CSP1263616 分钟前
特别节目————集训总结
c++
XY.散人16 分钟前
初识算法 · 滑动窗口(1)
算法
程序猿阿伟19 分钟前
《C++游戏人工智能开发:开启智能游戏新纪元》
c++·人工智能·游戏
韬. .38 分钟前
树和二叉树知识点大全及相关题目练习【数据结构】
数据结构·学习·算法
Word码43 分钟前
数据结构:栈和队列
c语言·开发语言·数据结构·经验分享·笔记·算法
五花肉村长1 小时前
数据结构-队列
c语言·开发语言·数据结构·算法·visualstudio·编辑器
一线青少年编程教师1 小时前
线性表三——队列queue
数据结构·c++·算法
C1 小时前
C++_智能指针详解
开发语言·c++
Neituijunsir1 小时前
2024.09.22 校招 实习 内推 面经
大数据·人工智能·算法·面试·自动驾驶·汽车·求职招聘