【Dijkstra模板】最短路

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);
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37862149/article/details/81746384