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
图论作为赛场上最重要的题型(?),一定要努力认真学好
来源:CSDN
作者:Raki_J
链接:https://blog.csdn.net/Raki_J/article/details/104095959