最短路算法
问题描述
在加权图上,两点之间的最小边权和路径称为最短路径。
常用算法
Dijkstra算法
Dijkstra算法本质上可以看做一种贪心算法,即每次由已定最短路点集找出最小拓展点,并把最小拓展点并入最短路点集。
对于Dijkstra的正确性的证明,我们先证明以下引理:
**引理:**对于一个连通的最短路点集,从点集中拓展出的不在最短路点集的最短点,一定是该点的最短点。
证明:用反证法(具体就不写了)
代码:
struct Node{
int id,dist;
}
Node makeNode(int id,int dist){
Node now;
now.id=id;now.dist=dist;
return now;
}
priority_queue<Node>q;
void Dijkstra(int s){
memset(use,0,sizeof use);
while(!q.empty()) q.pop();
for(int i=1;i<=n;++i) dis[i]=IFF;
q.push(makeNode(s,dis[s]=0));
while(!q.empty()){
Node now=q.top();q.pop();
if(now.dist<dis[now.id]||use[now.id]) continue;
use[now.id]=1;
for(int i=head[now.id];i;i=edge[i].pre){
int fr=now.id,to=edge[i].to;
if(dis[to]<=dis[fr]+edge[i].w) continue;
dis[to]=dis[fr]+edge[i].w;
q.push(makeNode(to,dis[to]));
}
}
}
队列优化的贝尔福特曼 s p f a spfa spfa
代码如下
queue<int>q;
void spfa(int s){
memset(use,0,sizeof use);
while(!q.empty()) q.pop();
for(int i=1;i<=n;++i)
dis[i]=IFF;
dis[s]=0;q.push(s);use[s]=1;
while(!q.empty()){
int now=q.front();q.pop();
use[now]=0;
for(int i=head[now];i;i=edge[i].pre){
int to=edge[i].to;
if(dis[to]<=dis[now]+edge[i].val) continue;
dis[to]=dis[now]+edge[i].val;
if(!use[to]){
use[to]=1;
q.push(to);
}
}
}
}