特色:是從起始點開始,採用貪心算法的策略,每次遍歷到始點距離最近且未訪問過的頂點的鄰接節點,直到擴展到終點爲止。node
舉例說明:c++
圖例來自《算法導論》算法
注意:要求圖中不存在負權邊。優化
樸素:code
void init() { memset(vis,0,sizeof(vis)); memset(d,0,sizeof(d)); memset(p,0,sizeof(p)); vis[sta]=1; for(int i=1;i<=n;++i) d[i]=a[sta][i]; for(int i=1;i<=n;++i) p[i]=sta; d[sta]=0; p[sta]=0; } void Dijkstra() { int k; init(); for(int i=1;i<=n-2;++i) { m=max1; for(int j=1;j<=n;++j) { if(d[j]<m && !vis[j]) {m=d[j]; k=j;} } if(m==max1) break; vis[k]=1; for(int j=1;j<=n;++j) if(d[k]+a[k][j]<d[j]) { d[j]=d[k]+a[k][j]; p[j]=k; } } printf("%d",d[end]); return ; }
堆優化:blog
#include<bits/stdc++.h> #define MAXN 100010 #define MAXM 500010 #define INF 0x3f3f3f3f struct EDGE{int to,dis,next;} e[MAXM]; struct node { int dis,pos; bool operator <( const node &x ) const {return x.dis < dis;} //重定向 }; std::priority_queue< node > q; int n,m,s; int adj[MAXN],dis[MAXN],cnt; bool vis[MAXN]; void addedge(int u,int v,int d) //鏈式前向星 { ++cnt; e[cnt].dis=d; e[cnt].to=v; e[cnt].next=adj[u]; adj[u]=cnt; } void Dijkstra() { dis[s]=0; q.push(( node ){0,s}); //先將源點入隊列 while(!q.empty()) { node temp=q.top(); q.pop(); int x=temp.pos; if(vis[x]) continue; //對未訪問節點進行掃描 vis[x]=1; for(int i=adj[x];i;i=e[i].next) { int y=e[i].to; if(dis[y]>dis[x]+e[i].dis) //三角不等式 { dis[y]=dis[x]+e[i].dis; if(!vis[y]) q.push( (node){dis[y], y} ); //鄰接節點入隊列 } } } } int main() { scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=n;++i) dis[i]=INF; //初始化 for(int i=0;i<m;++i) { int u,v,d; scanf("%d%d%d",&u,&v,&d); addedge(u,v,d); } Dijkstra(); for(int i=1;i<=n;++i) printf("%d ",dis[i]); return 0; }
作題感悟:隊列