Dijkstra:
将问题分解为子问题:若A为当前以得最短路径的所有点的集合,由于要将做有点都访问到(以便更好的做relaxation),所以必定要在当前位置选一个点加入集合A。为了使A性质不变,则加入剩余未访问到的点中、离源点s最近的一个点。继续relax。
重复操作,直至所有点加入A。
代码如下: //参见BZOJ 1169
void dijkstra(int s,int t) //n为顶点数,顶点为1-n,用邻接矩阵存放
{
for(int i=1;i<=n;i++)
dist[i]=INF;
dist[s]=0;
fa[s]=0;
vis[s]=true;
for(int i=1;i<=n;i++)
if(a[s][i]){
dist[i]=1;
fa[i]=s;
}
for(int i=1;i<=n;i++){
int min=INF,k;
for(int j=1;j<=n;j++)
if(!vis[j]&&dist[j]<min){
min=dist[j];
k=j;
}
vis[k]=true;
for(int j=1;j<=n;j++)
if(a[k][j]&&!vis[j]&&dist[k]+a[k][j]<dist[j]){
dist[j]=dist[k]+a[k][j];
fa[j]=k;
}
}
}
****dijkstra的堆优化:用邻接表存放
struct node_{
int v,dist;
};
struct cmp{
bool operator()(node_ x,node_ y){
if(x.dist==y.dist) return x.v>y.v; //1169题目要求字典序,但加上了也挺好的
return x.dist>y.dist;
}
};
//反起来的
priority_queue<node_,vector<node_>,cmp> q; //定义一个优先队列,代替用循环找距s dist[]最小的点
void dijkstra(int s,int t)
{
for(int i=1;i<=n;i++)
dist[i]=INF;
fa[s]=0;
node_ c,d;
c.v=s,c.dist=dist[s]=0;
q.push(c);
while(!q.empty()){
c=q.top();
q.pop();
int u=c.v;
if(vis[u]) continue;
vis[u]=true;
for(node *p=adj[u];p;p=p->next){
int v=p->v,w=p->w;
if(dist[u]+w<dist[v]){
dist[v]=dist[u]+w;
fa[v]=u;
d.v=v,d.dist=dist[v];
q.push(d);
}
}
}
}