Dijkstra算法:求正权图中的单源最短路径
1、有向图Dijkstra堆优化代码:
1 #define INF 0x7fffffff 2 #include<queue> 3 #include<cstdio> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 const int N = 100005; 8 const int M = 500005; 9 struct edge 10 { 11 int to,dis,next; 12 }e[M]; 13 int head[N],dis[N],cnt; 14 bool vis[N]; 15 int n,m,s; 16 void add(int u,int v,int d) 17 { 18 ++cnt; 19 e[cnt].dis=d; 20 e[cnt].to=v; 21 e[cnt].next=head[u]; 22 head[u]=cnt; 23 } 24 struct node 25 { 26 int dis,pos; 27 }; 28 bool operator < (const node &x,const node &y) 29 { 30 return x.dis<y.dis; 31 } 32 priority_queue<node> q; 33 inline void dijkstra() 34 { 35 dis[s]=0; 36 q.push((node){0,s}); 37 while(!q.empty()) 38 { 39 node tmp=q.top(); 40 q.pop(); 41 int x=tmp.pos,d=tmp.dis; 42 if(vis[x]) continue; 43 vis[x]=1; 44 for(int i=head[x];i;i=e[i].next) 45 { 46 int y=e[i].to; 47 if(dis[y]>dis[x]+e[i].dis) 48 { 49 dis[y]=dis[x]+e[i].dis; 50 if(!vis[y]) q.push((node){dis[y],y}); 51 } 52 } 53 } 54 } 55 int main() 56 { 57 cin>>n>>m>>s; 58 for(int i=1;i<=n;++i) dis[i]=INF; 59 for(int i=0;i<m;++i) 60 { 61 int u,v,d; 62 cin>>u>>v>>d; 63 add(u,v,d); 64 } 65 dijkstra(); 66 for(int i=1;i<=n;++i) 67 cout<<dis[i]<<" "; 68 cout<<endl; 69 return 0; 70 }
2、无向图Dijkstra堆优化代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<queue> 5 using namespace std; 6 const int N = 10005; 7 const int INF = 0x7fffffff; 8 struct node 9 { 10 int x,d; 11 node(int a,int b){x=a;d=b;} 12 }; 13 bool operator <(const node &x,const node &y) 14 { 15 return x.d<y.d; 16 } 17 vector<node> eg[N]; 18 int dis[N],n; 19 void Dijkstra(int s) 20 { 21 int i; 22 for(i=0;i<=n;i++) dis[i]=INF; 23 dis[s]=0; 24 priority_queue<node> q; 25 q.push(node(s,dis[s])); 26 while(!q.empty()) 27 { 28 node x=q.top();q.pop(); 29 for(i=0;i<eg[x.x].size();i++) 30 { 31 node y=eg[x.x][i]; 32 if(dis[y.x]>x.d+y.d) 33 { 34 dis[y.x]=x.d+y.d; 35 q.push(node(y.x,dis[y.x])); 36 } 37 } 38 } 39 } 40 int main() 41 { 42 int a,b,d,m; 43 cin>>n>>m>>s; 44 //处理多组数据时,使用 for(int i=0;i<n;++i) eg[i].clear(); 45 while(m--) 46 { 47 cin>>a>>b>>d; 48 eg[a].push_back(node(b,d)); 49 eg[b].push_back(node(a,d)); 50 } 51 Dijkstra(s); 52 cout<<dis[n]<<endl; 53 return 0; 54 }
3、题目:Luogu最短路模板1 Luogu最短路模板2 Luogu最短路模板3
*看题解时,发现有大佬使用zkw线段树来优化Dijkstra算法,这里粘贴上代码与链接:
1 #include <algorithm> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <ctime> 7 #include <iostream> 8 #include <map> 9 #include <queue> 10 #include <set> 11 #include <stack> 12 #include <string> 13 #include <vector> 14 using namespace std; 15 #define go(i, j, n, k) for (int i = j; i <= n; i += k) 16 #define fo(i, j, n, k) for (int i = j; i >= n; i -= k) 17 #define rep(i, x) for (int i = h[x]; i; i = e[i].nxt) 18 #define mn 100010 19 #define mm 200020 20 #define inf 2147483647 21 #define ll long long 22 #define ld long double 23 #define fi first 24 #define se second 25 #define root 1, n, 1 26 #define lson l, m, rt << 1 27 #define rson m + 1, r, rt << 1 | 1 28 #define bson l, r, rt 29 inline int read(){ 30 int f = 1, x = 0;char ch = getchar(); 31 while (ch > '9' || ch < '0'){if (ch == '-')f = -f;ch = getchar();} 32 while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} 33 return x * f; 34 } 35 inline void write(int x){ 36 if (x < 0)putchar('-'),x = -x; 37 if (x > 9)write(x / 10); 38 putchar(x % 10 + '0'); 39 } 40 //This is AC head above... 41 struct node{ 42 int v, nxt, w; 43 } e[mm << 1]; 44 int h[mn], p; 45 inline void add(int a,int b,int c){ 46 e[++p].nxt = h[a]; 47 h[a] = p; 48 e[p].v = b; 49 e[p].w = c; 50 } 51 int dis[mn]; 52 int n, m, s, t; 53 struct tree{ 54 int minw, minv; 55 }; 56 struct SegmentTree{ 57 tree z[mn << 2]; 58 inline void update(int rt){ 59 z[rt].minw = min(z[rt << 1].minw, z[rt << 1 | 1].minw);//维护区间最小值 60 z[rt].minv = (z[rt << 1].minw < z[rt << 1 | 1].minw) ? z[rt << 1].minv : z[rt << 1 | 1].minv;//维护区间最小值位置 61 } 62 inline void build(int l,int r,int rt){//建树 63 if(l==r){ 64 z[rt].minw = l == s ? 0 : inf;//我们可以直接建树时把s的点设置为0 65 z[rt].minv = l;//记录最小值位置,方便修改 66 return; 67 } 68 int m = (l + r) >> 1; 69 build(lson); 70 build(rson); 71 update(rt); 72 } 73 inline void modify(int l,int r,int rt,int now,int v){//单点修改 74 if(l==r){ 75 z[rt].minw = v; 76 return; 77 } 78 int m = (l + r) >> 1; 79 if(now<=m) 80 modify(lson, now, v); 81 else 82 modify(rson, now, v); 83 update(rt); 84 } 85 } tr; 86 inline void Dij(){//Dijkstra的核心部分 87 go(i,1,n,1){ 88 dis[i] = inf; 89 }//初始化dis 90 dis[s] = 0; 91 while(tr.z[1].minw < inf){//这里就是判断是否为空 92 int x = tr.z[1].minv;//取整个线段树中最小的点 93 tr.modify(root, x, inf);//单点修改最小的点为inf 94 rep(i,x){ 95 int v = e[i].v; 96 if(dis[v] > dis[x] + e[i].w){ 97 dis[v] = dis[x] + e[i].w; 98 tr.modify(root, v, dis[x] + e[i].w);//这里就是类似入队操作 99 } 100 } 101 } 102 } 103 int main(){ 104 n = read(), m = read(), s = read(), t=read(); 105 go(i,1,m,1){ 106 int x = read(), y = read(), v = read(); 107 add(x, y, v); 108 add(y, x, v);//这个一定记住,无向图要正反两条边 109 } 110 tr.build(root);//建树 111 Dij();//Dijkstra 112 cout << dis[t]; 113 return 0; 114 }
链接←