朴素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));
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;
q.push(node(dist[e.to],e.to)) ;
}
}
}
}
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;
}