最短路算法(dijkstra,bellman_ford,floyd)

最短路算法

dijkstra(初级的最短路算法,适合稠密图,可用邻接表优化)

bool relax(int u,int v)

{

    double tmp=max(dist[u],edge[u][v]);

    if(tmp<dist[v]){

        dist[v]=tmp;

    }

}



void dijkstra()

{

    memset(vis,0,sizeof(vis));

    for(int i=0;i<n;i++){

        int x;

        double mindist=INF;

        for(int j=0;j<n;j++){

            if(vis[j]) continue;

            if(dist[j]<mindist) mindist=dist[x=j];

        }

        vis[x]=1;

        for(int v=0;v<n;v++){

            if(v==x) continue;

            relax(x,v);

        }

    }

}
dijkstra

bellman_ford(实用高效的最短路算法,实际复杂度远小于最坏复杂度o(NM),可判断负环)

bool bellman_ford() //bool 判断是否有负环

{

    for(int i=0;i<n;i++) dist[i]=(i==s)0:INF;

    for(int i=0;i<n-1;i++){ //松弛n-1次,实际小于n-1次

        bool flag=0;        //此变量判断能否继续松弛,若不能退出算法

        for(int j=0;j<e;j++){

            if(relax(j)) flag=1;

        }

        if(dist[s]<0) return true;

        if(!flag) return false;

    }

    for(int i=0;i<e;i++){    //此处检查负环,如果松弛了n-1次还能继续松弛说明有负环

        if(relax(i)) return true;

    }

    return false;

}
负环版
int bellman_ford()

{

    for(int i=0;i<n;i++) dist[i]=(i==s)0:INF;

    for(int i=0;i<n-1;i++){

        bool flag=0;

        for(int j=0;j<e;j++){

            if(relax(j)) flag=1;

        }

        if(!flag) break;

    }

    return dist[s];

}
最短路版

 floyd(适合求任意两点的最短路或传递闭包判断拓扑序列,时间复杂度较高)

void floyd()

{

    for(int k=1;k<=n;k++){

        for(int u=1;u<=n;u++){

            for(int v=1;v<=n;v++){

                if(edge[u][v]<edge[u][k]+edge[k][v]) edge[u][v]=edge[u][k]+edge[k][v];

            }

        }

    }

}



/*

传递闭包:将循环内改成这样即可:

   if(G[u][k]&&G[k][v]) G[u][v]=1;

*/
floyd

除此之外求最短路还有SPFA,A*等算法,以后再慢慢学------

 ===================================================================================================

补充,SPFA算法

int N,M,S,T;

bool vis[maxn];

ll dist[maxn];

int c[maxn];

struct Edge

{

    int v;

    ll w;

    Edge *next;

};Edge e[maxn*10];



bool relax(int u,int v,ll w)

{

    if(dist[u]+w<dist[v]){

        dist[v]=dist[u]+w;

        return true;

    }

    return false;

}



void add_edge(int u,int v,ll w) ///插入邻接表的首部而非尾部,避免遍历

{

    Edge *pre=&e[u];

    Edge *p=(Edge*)malloc(sizeof(Edge));

    p->v=v;p->w=w;

    p->next=pre->next;

    pre->next=p;

}



bool spfa()

{

    for(int i=1;i<=N;i++) dist[i]=(i==S)?0:INF;

    memset(vis,0,sizeof(vis));

    memset(c,0,sizeof(c));

    queue<int> q;

    q.push(S);

    vis[S]=1;c[S]++;

    while(!q.empty()){

        int u=q.front();q.pop();vis[u]=0;

        for(Edge *p=e[u].next;p!=NULL;p=p->next){ ///遍历队首结点的每条出边

            int v=p->v;

            ll w=p->w;

            if(relax(u,v,w)){

                if(!vis[v]){

                    q.push(v);

                    vis[v]=1;

                    c[v]++;

                    if(c[v]>N) return false;

                }

            }

        }

    }

    return true;

}
View Code

 

你可能感兴趣的:(dijkstra)