• 图论-最短路模版


    Dijkstra算法-邻接矩阵形式

    复杂度:N^2

    /*
    * Dijkstra算法,邻接矩阵形式:
    * 复杂度为O(n^2),仅可处理非负权图
    * cost:    任意两点边权(不相连边需赋值INF)
    * n:       图中点的总数(当前点从0开始编号)
    * lowcost:任意点到源点的最短路
    * beg:    源点
    */
    const int MAXN=1010;
    #define typec int
    const typec INF=0x3f3f3f3f;
    bool vis[MAXN];
    int pre[MAXN];
    void Dijkstra(typec cost[][MAXN],typec lowcost[],int n,int beg)
    {
        for(int i=0;i<n;i++)
        {
            lowcost[i]=INF;
            vis[i]=false;
            pre[i]=-1;
        }
    
        lowcost[beg]=0;
        for(int j=0;j<n;j++)
        {
            int k=-1;
            int Min=INF;
            for(int i=0;i<n;i++)
            if(!vis[i]&&lowcost[i]<Min)
            {
                Min=lowcost[i];
                k=i;
            }
            if(k==-1)break;
            vis[k]=true;
            for(int i=0;i<n;i++)
            if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i])
            {
                lowcost[i]=lowcost[k]+cost[k][i];
                pre[i]=k;
            }
        }
    }

    Dijkstra算法-邻接表形式

    复杂度:Elog(E)

    /*
    * 优化Dijkstra,邻接表形式
    * 复杂度O(ElogE),仅适合无负权图
    * E[i]:  与i点相连的边的集合,初始化方式: E[i].clear()
    * n:    图中点的总数,(节点编号从1开始)
    * start: 源点
    * dist:  各点到源点的最短路
    * MAXN:  最大边数
    */
    const int INF=0x3f3f3f3f;
    const int MAXN=1000010;
    struct qnode
    {
        int v;
        int c;
        qnode(int _v=0,int _c=0):v(_v),c(_c){}
        bool operator <(const qnode &r)const
        {
            return c>r.c;
        }
    };
    struct Edge
    {
        int v,cost;
        Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
    };
    
    vector<Edge>E[MAXN];
    bool vis[MAXN];
    int dist[MAXN];
    void Dijkstra(int start,int n)//点的编号从1开始
    {
        memset(vis,false,sizeof(vis));
        for(int i=1;i<=n;i++)dist[i]=INF;
        priority_queue<qnode>que;
        while(!que.empty())que.pop();
        dist[start]=0;
        que.push(qnode(start,0));
        qnode tmp;
        while(!que.empty())
        {
            tmp=que.top();
            que.pop();
            int u=tmp.v;
            if(vis[u])continue;
            vis[u]=true;
            for(int i=0;i<E[u].size();i++)
            {
                int v=E[tmp.v][i].v;
                int cost=E[u][i].cost;
                if(!vis[v]&&dist[v]>dist[u]+cost)
                {
                    dist[v]=dist[u]+cost;
                    que.push(qnode(v,dist[v]));
                }
            }
        }
    }
    
    void addedge(int u,int v,int w)
    {
        E[u].push_back(Edge(v,w));
    }
    //---------------------------------------------------------------

    SPFA算法-邻接表形式

    复杂度:kE

    /*
    * SPFA,邻接表形式
    * 复杂度O(kE)(复杂度不定,改成栈有时更快),可处理负权图
    * E[i]:  与i点相连的边的集合,初始化方式: E[i].clear()
    * n:    图中点的总数,(节点编号从1开始)
    * start: 源点
    * dist:  各点到源点的最短路
    * MAXN:  最大点数
    */
    
    const int MAXN=1010;
    const int INF=0x3f3f3f3f;
    struct Edge
    {
        int v;
        int cost;
        Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
    };
    vector<Edge>E[MAXN];
    void addedge(int u,int v,int w)
    {
        E[u].push_back(Edge(v,w));
    }
    bool vis[MAXN];//在队列标志
    int cnt[MAXN];//每个点的入队列次数
    int dist[MAXN];
    bool SPFA(int start,int n)
    {
        memset(vis,false,sizeof(vis));
        for(int i=1;i<=n;i++)dist[i]=INF;
        vis[start]=true;
        dist[start]=0;
        queue<int>que;
        while(!que.empty())que.pop();
        que.push(start);
        memset(cnt,0,sizeof(cnt));
        cnt[start]=1;
        while(!que.empty())
        {
            int u=que.front();
            que.pop();
            vis[u]=false;
            for(int i=0;i<E[u].size();i++)
            {
                int v=E[u][i].v;
                if(dist[v]>dist[u]+E[u][i].cost)
                {
                    dist[v]=dist[u]+E[u][i].cost;
                    if(!vis[v])
                    {
                        vis[v]=true;
                        que.push(v);
                        if(++cnt[v]>n)return false;
                        //cnt[i]为入队列次数,用来判定是否存在负环回路
                    }
                }
            }
        }
        return true;
    }

    Ford算法-邻接表形式

    复杂度:NE

    /*
    * bellman_ford算法,邻接表形式
    * 复杂度O(VE),可处理负权图
    * E:       边集,初始化方式: E.clear()
    * n:    图中点的总数,star
    * start: 源点
    * dist:  各点到源点的最短路
    * MAXN: 最大点数
    * 可以判断是否存在负环回路。返回true,当且仅当图中不包含从源点可达的负权回路
    */
    
    const int INF=0x3f3f3f3f;
    const int MAXN=550;
    int dist[MAXN];
    struct Edge
    {
        int u,v;
        int cost;
        Edge(int _u=0,int _v=0,int _cost=0):u(_u),v(_v),cost(_cost){}
    };
    vector<Edge>E;
    bool bellman_ford(int start,int n)//点的编号从1开始
    {
        for(int i=1;i<=n;i++)dist[i]=INF;
        dist[start]=0;
        for(int i=1;i<n;i++)//最多做n-1次
        {
            bool flag=false;
            for(int j=0;j<E.size();j++)
            {
                int u=E[j].u;
                int v=E[j].v;
                int cost=E[j].cost;
                if(dist[v]>dist[u]+cost)
                {
                    dist[v]=dist[u]+cost;
                    flag=true;
                }
            }
            if(!flag)return true;//没有负环回路
        }
        for(int j=0;j<E.size();j++)
        if(dist[E[j].v]>dist[E[j].u]+E[j].cost)
        return false;//有负环回路
        return true;//没有负环回路
    }
    
    void addedge(int u,int v,int w)
    {//加的是单向边,即u->v权值为w
        E.push_back(Edge(u,v,w));
    }

    Ford算法-求任意最短路

    复杂度:N^3

    //---O(n^3)的任意最短
        for(int k = 0; k < n; k++)
            for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
            if(cost[i][j]<cost[i][k]*cost[k][j])
            cost[i][j]=cost[i][k]*cost[k][j];
    //--------------------------------------------
  • 相关阅读:
    Windows10切换其他用户身份运行程序
    管理Windows功能
    如何暂时锁定您的键盘
    判断远程计算机基于x64或x86处理器
    复制文件而不在命令行中覆盖它们
    解决IDEA Gradle工程控制台输出乱码
    jquery 选择器、属性和CSS、文档处理、筛选、事件、动画效果
    IDEA炫酷主题推荐!(转)
    Windows 查看端口占用进程并关闭(转)
    JVM(二)--运行时数据区
  • 原文地址:https://www.cnblogs.com/mochenmochen/p/5156885.html
Copyright © 2020-2023  润新知