zoukankan      html  css  js  c++  java
  • 最短路算法(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
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    20110603 本日跌的股票之后一段时间轻易不要碰
    一日三省
    火电排污新标准年内出台 撬动千亿脱硝市场
    20082011大股东增持专题
    收评:5月24日资金流向(摘自益盟)
    2011年中期业绩预增前20家公司
    2011大股东十大增持概念股全景图
    放不下期货
    从众是通向地狱最廉价的门票
    在ASP.NET中获取Get方式和Post方式提交的数据
  • 原文地址:https://www.cnblogs.com/--560/p/4329978.html
Copyright © 2011-2022 走看看