Dijkstra

允我心安 提交于 2020-01-28 00:30:26

Dijkstra求最短路

今天花了一天的时间开始学习图论的第一个算法dij,根据大佬们说的,没有负边权用dijkstra,有负边权用SPFA(死了?)or bellman-ford?

用的链式前向星建图

用优先队列(堆)优化之后复杂度大概是O(m*logn)

模板题 洛谷P4779

题目描述
给定一个 nn 个点,mm 条有向边的带非负权图,请你计算从 ss 出发,到每个点的距离。

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

输入格式
第一行为三个正整数 n, m, sn,m,s。 第二行起 mm 行,每行三个非负整数 u, v, w
输出格式
输出一行 nn 个空格分隔的非负整数,表示 ss 到每个点的距离。

输入输出样例
输入 #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

#include<bits/stdc++.h>
using namespace std;
#define maxn 20000010
#define maxm 20000010
#define INF  99999999999999999
#define int long long
inline int read()
{
    int x=0,k=1; char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')k=-1;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*k;
}//快速读入
struct edge{
	int u,v,w,next;                      //出发点,到达点,权值
}e[maxm];
int head[maxn],cnt,n,m,s,vis[maxn],dis[maxn];
inline int add(int u,int v,int w){
	e[++cnt].v=v; //出发点
	e[cnt].u=u;//到达点
	e[cnt].w=w;//权值
	e[cnt].next=head[u];//该点的下一条边
	head[u]=cnt; //该点的最后一条边
	 //链式前向星建图
} 
struct node{
	int w,now;
	bool operator <(const node&x)const//重载预算符,小根堆
	{
		return w>x.w;
	}
};
priority_queue<node>q;
inline void dij(){
	for(int i=1;i<=n;i++){
		dis[i]=INF;//初始化
	}
	dis[s]=0;
	q.push((node){0,s});
	while(!q.empty()){
		node x=q.top();
		q.pop();
		int u=x.now;//取u为现在访问的点,为第u个点
		if(vis[u]) continue;//如果访问过则跳过
		vis[u]=1;
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].v;//起点
			if(dis[v]>dis[u]+e[i].w){
				dis[v]=dis[u]+e[i].w;//更新最短路径值,我认为这像DP,但是叫松弛操作?这个词还不是很懂
				q.push((node){dis[v],v});//压入这个点继续
			}
		}
	}
}
signed main(){
	n=read(),m=read(),s=read();
	for(int i=1,x,y,z;i<=m;i++){
		x=read(),y=read(),z=read();
		add(x,y,z);
	}
	dij();
	for(int i=1;i<=n;i++){
		printf("%lld ",dis[i]);
	}
	return 0;
}

让我很迷的一点就是这题能过强数据版本,但是弱数据版本就全部RE…不是很懂,改了还是RE

图论作为赛场上最重要的题型(?),一定要努力认真学好

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!