朴素Dijstra单源最短路算法:
#include<cstdio> #include<iostream> using namespace std; const int inf=2e9; int map[105][105],dist[105],m,n,x,y; //s[i]数组保存到i的最短路长度 bool vis[105]; void input(){ int p,q,i,j,t; scanf("%d%d",&n,&m); for(i=1;i<=m;i++){ scanf("%d%d%d",&p,&q,&t); map[p][q]=t; } for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(!map[i][j])map[i][j]=inf; //初始化 scanf("%d%d",&x,&y); } void dijkstra(){ int i,k,j; for(i=1;i<=n;i++)dist[i]=map[x][i]; vis[x]=true; do{ int minn=inf; k=0; for(i=1;i<=n;i++) //找到未讨论的最近点 if(!vis[i]&&dist[i]<minn) minn=dist[i],k=i; if(k>0){ vis[k]=true; for(i=1;i<=n;i++) dist[i]=min(dist[i],dist[k]+map[k][i]); //更新到i的最短路长度 } }while(k>0); printf("%d",s[y]); } int main(){ input(); dijkstra(); }
该算法也可以适用于无向图,但要求图中不能有负权。
dijkstra也可以求解次短路,只需要把dist和vis改成二维数组,但是如果有重边,则必须改为用边存图。
代码如下:
void dijkstra(int s) { int i,j,k,t,y,z,minn; for(i=1;i<=n;i++){ //初始化 dis[i][0]=dis[i][1]=inf; //dis[i][0]表示最短路,dis[i]1]表示次短路。 vis[i][0]=vis[i][1]=false; } dis[s][0]=0; do{ k=0; minn=inf; for(i=1;i<=n;i++){ if(!vis[i][0]&&dis[i][0]<minn) //找到讨论点 minn=dis[i][0],k=i,t=0; else if(!vis[i][1]&&dis[i][1]<minn) minn=dis[i][1],k=i,t=1; } if(k>0){ vis[k][t]=true; j=last[k]; while(j!=0){ y=line[j].end; z=line[j].len; if(minn+z<dis[y][0]) { dis[y][1]=dis[y][0]; dis[y][0]=minn+z; } else if((minn+z<dis[y][1])&&(minn+z>dis[y][0])) dis[y][1]=minn+z; j=line[j].next; } } }while(k>0); }
使用边存储和优先队列优化的,结构体形式版Dijstra:
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<vector> #define CLEAR(XXX) memset((XXX),0,sizeof(XXX)) using namespace std; const int inf=1e9; const int maxn=1005,maxm=1005; int n,m; inline void _read(int &x){ char ch=getchar(); bool mark=false; for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true; for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0'; if(mark)x=-x; } struct Edge{ int from,to,w; Edge(int from,int to,int w):from(from),to(to),w(w){} }; struct node{ //建小根堆用 int d,u; node (int d,int u):d(d),u(u){} bool operator < (const node& a)const { return d>a.d; } }; struct Dijstra{ int n,m; vector<Edge> edge; int last[maxm],Next[maxm],dist[maxn]; bool vis[maxn]; void init(int n){ this->n = n; m=0; CLEAR(last); CLEAR(Next); edge.clear(); edge.push_back(Edge(0,0,0)); } void add_edge(int from,int to,int dist){ edge.push_back(Edge(from,to,dist)); m=edge.size()-1; Next[m]=last[from]; last[from]=m; } void solve(int s){ int i; priority_queue <node> q; CLEAR(vis); for(i=1;i<=n;i++) dist[i]=inf; dist[s]=0; q.push(node(0,s)); vis[s]=true; while(!q.empty()){ int x=q.top().u; q.pop(); for(i=last[x];i;i=Next[i]){ Edge& e=edge[i]; if(dist[e.from]+e.w<dist[e.to]){ dist[e.to]=dist[e.from]+e.w; if(!vis[e.to]){ q.push(node(dist[e.to],e.to)) ; vis[e.to]=true; } } } } } }; int main(){ Dijstra solver; int i,j,x,y,w; _read(n);_read(m); solver.init(n); for(i=1;i<=m;i++){ _read(x);_read(y);_read(w); solver.add_edge(x,y,w); } _read(x);_read(y); solver.solve(x); printf("%d",solver.dist[y]); return 0; }