最短路问题是图论中最基础的问题,在面试题中出现的次数也很多,很多类似最少步数等问题都能转化到最短路问题,这篇文章介绍单源最短路问题的两种算法。单源最短路问题是固定一个起点,求它到其他所有点的最短路问题,如果只求两个固定点之间的最短路,看起来要简单很多,但其实复杂度是一样的,所以我们广泛的讨论单源最短路问题。
struct edge{ int from, to , cost} //边的结构体:顶点from到顶点to的权值cost
edge es[MAX_E]; //边的数组
int d[MAX_V]; //距离的数组
int V,E; //顶点数和边数
void shortest_path(int s){
for (int i=0;i<V;i++)
d[i]=INF;
d[s]=0;
while(true)
bool update=false;
for(int i=0;i<E;i++)
edge e=es[i];
if(d[e.from]!=INF&&d[e.to]>d[e.form]+e.cost){ //从已经想连的顶点中找到满足条件的
d[e.to]=d[e.from]+e.cost;
update=true;
}
}
if(!update) break; //所有顶点都更新过后,结束
}
}复杂度:while最多循环|V|-1次,所以是O(|V|*|E|)。int cost[MAX_V][MAX_E]
int d[MAX_V];
bool used[MAX_V];
int V;
void dijkstra(int s){
fill(d,d+V,INF);
fill(used,used+V,false);
d[s]=0;
while(true){
int v=-1;
for(int u=0;u<V;u++){ //从未使用的顶点中选择一个距离最小的顶点(while的第一次循环选择的是点s)
if(!used[u]&&(v==-1||d[u]<d[v]))
v=u;
}
if (v==-1) break;
used[v]=true;
for(int u=0;u<V;u++){
d[u]=min(d[u],d[v]+cost[v][u]); //更新和确定的点相连的点的距离
}
}
}这种写法的复杂度是O(|V|^2),代码中大部分时间花在查找下一个使用的顶点上,我们可以使用好的数据结构保护好这个顶点,在有数值插入的情况下要得到集合中的最小值,那么最好的数据结构是堆,堆中元素有O(|V|)个,需要更新O(|E|)次,所以复杂度为O(|E|log|V|)。struct edge{int to, cost}
typedef pair<int ,int> P; //first是最短距离,second是顶点编号
int d[MAX_V];
vector<edge> G[MAX_V];//邻接表
int V;
void dijkstra(int s){
priority_queue<P,vector<p>,greater<p>> que; //greater表示从小到大
fill(d,d+V,INF);
d[s]=0;
que.push(P(0,s));
while(!que.empty()){
P p=que.top(); //取出确定点
que.pop();
int v=p.second;
if(d[v]<p.first) continue;
for(int i=0;i<G[v].size();i++)
{
edge e=G[v][i]; //边为从点v到点i
if(d[e.to]>d[v]+e.cost;){
d[e.to]=d[v]+e.cost;
que.push(P(d[e.to],e.to)); //把更新的距离和点放进堆
}
}
}
}如果使用斐波那契堆,性能还能提高,就是有点复杂。原文地址:http://blog.csdn.net/ji_zailushang/article/details/24670881