单源最短路径

发布于:2024-03-29 ⋅ 阅读:(27) ⋅ 点赞:(0)

题目描述

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

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

输入格式

第一行为三个正整数n,m,s。 第二行起 m 行,每行三个非负整数 ui​,vi​,wi​,表示从 ui​ 到 vi​ 有一条权值为 wi​ 的有向边。

输出格式

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

输入输出样例

输入

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

这就是一道图。

但是用邻接矩阵太浪费空间了,还是用邻接表好一点,邻接表,用的是动态数组,这样会节省空间。

这里定义一个结构体node,里面两个int元素,to和dis,to是到达的节点,dis表示路径长度,让后建立动态数组a,数据类型设为node,输入时的存储就像这样:

a[u].push_back(node{v,w});

 

然后就是写搜索函数,这道题使用的算法是dijkstra

用在这道题上面,那就把点分为两种,蓝点和白点,蓝点就是没有确定最小值的,而白点就是已经确定了的,从s开始找他通往的所有蓝点y,用数组dis记录到达y点的长度,接着,再从剩下的蓝点中,找一个值最小的,标记为白点,以他为基础,查找与之相连的蓝点,如此循环

然后要注意,记录dis记录的同时,如果元素没被访问,就进行入队操作。

最后输出dis数组的值就行了

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int n,m,s;
struct node{
	int to,dis;
	friend bool operator <(node a,node b){
		return a.dis>b.dis;
	}
};
priority_queue<node>q;
vector<node>a[N];
int dis[N];
int vis[N];
void dij(){
	for(int i=1;i<=n;i++)dis[i]=INT_MAX;
	dis[s]=0;
	q.push(node{s,0});
	while(!q.empty()){
		node t=q.top();
		q.pop();
		int x=t.to;
		if(vis[x]==1)continue;
		vis[x]=1;
		for(int i=0;i<a[x].size();i++){
			int y=a[x][i].to;
			int z=a[x][i].dis;
			dis[y]=min(dis[y],dis[x]+z);
			if(vis[y]==0)q.push(node{y,dis[y]});
		}
	}
}
signed main(){
	scanf("%lld%lld%lld",&n,&m,&s);
	int u,v,w;
	for(int i=1;i<=m;i++){
		scanf("%lld%lld%lld",&u,&v,&w);
		a[u].push_back(node{v,w});
	}
	dij();
	for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
}

本文含有隐藏内容,请 开通VIP 后查看