zoukankan      html  css  js  c++  java
  • 9.3 整理一下最短路算法

    之前学得好多算法都没写博客 ,来补一下板子

    思想:

    dijkstra:贪心思想+最短路的最优子结构特性(也正是因为有负权的图没有此特性,因而不能适用

    Bellman-Ford:动态逼近,不断松弛,算法基于这样一个事实:一条最短路最多包括V-1条边,所以进行E*V次松弛即可求得所有的单源最短路(否则就走重复啦),若V*E次后还可以松弛,则一定存在负权圈

    spfa:可以看做bf的队列优化,动态逼近,检测对一个点连接的所有边松弛后能否继续松弛更新,松弛到不能再松弛,最终所得即答案(负权圈会无限松弛,所以不能用

    floyd:最优子结构+递推,让人感觉很浑厚优雅的算法

    复杂度:

    dijkstra:堆优化后可达O(E+VlgV)

    Bellman-Ford:O(V*E)

    spfa:O(2*E)~O(V*E),不稳定,和图的稠密程度有关

    floyd:O(E^3)

    适用条件:

    (1)当权值为非负时,用Dijkstra。
    (2)当权值有负值,且没有负圈,则用SPFA,SPFA能检测负圈,但是不能输出负圈。
    (3)当权值有负值,而且可能存在负圈,则用BellmanFord,能够检测并输出负圈。
    (4)SPFA检测负环:当存在一个点入队大于等于V次,则有负环。
    (5)多源最短路且顶点不多用floyd,floyd还可以检测无向图中最小环

    板子:

    bellman:

    // Bellman Ford 
    
    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn  = 100;
    const int inf = 0x3f3f3f3f;
    
    struct Edge{
         int u ,v ,w;
    }edge[maxn];
    
    int start ,V ,E ,dis[maxn];
    
    void init( ){
    //输入图
         cin>>V>>E>>start;
         memset( dis ,inf ,sizeof( dis) );
         dis[start] = 0;
         //初始化
         for( int i = 1 ;i <= E ;i++ ){
             cin >>edge[i].u>>edge[i].v>>edge[i].w;
             if( edge[i].u == start )dis[ edge[i].v ] = edge[i].w;
             //初始化源点直接相邻点的距离
         }
    }
    
    void realex( int u ,int v ,int w ){
         dis[v] = min( dis[v] ,dis[u] + w );
    }
    
    bool bellman( ){
         for( int i =1 ;i<= V ;i++ ){
             for( int j = 1; j<= E ;j++ )
                  realex( edge[j].u ,edge[j].v ,edge[j].w );
         }
    
         //负环检测--如果还能继续松弛则有负环
         for( int j = 1; j<= V ;j++ )
             if( dis[ edge[j].v ]  > dis[ edge[j].u ] + edge[j].w  )
    return false; return true; } int main( ){ init( ); if( bellman( ) ){ for( int i = 1; i<= V ;i++ ){ cout<<start<<" --> "<<i<<" : "<<dis[i]<<endl; } } else cout<<" has negetive circle. "<<endl; return 0; }

     spfa:(链式前向星存边

    void spfa(int x) {
        memset(d, inf, sizeof(d)); 
        memset(v, 0, sizeof(v)); 
        d[x] = 0; v[x] = 1;
        q.push(x);
        while (q.size()) {
    
            int x = q.front(); q.pop();
            v[x] = 0;
    
            for (int i = head[x]; i; i = Next[i]) {
                int y = ver[i], z = edge[i];
                if (d[y] > d[x] + z) {
                    d[y] = d[x] + z;
                    if (!v[y]) q.push(y), v[y] = 1;
                }
            }
        }
    }

    floyd:

    for(k=1;k<=n;k++)
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                if(dis[i][j]>dis[i][k]+dis[k][j])
                     dis[i][j]=dis[i][k]+dis[k][j];

     floyd求最小环:

            for (int k=1;k<=n;k++){
                for (int i=1;i<=n;i++){
                    for (int j=1;j<=n;j++){
                        if (i==j||j==k||i==k) continue;
                        ans=min(ans,a[k][j]+a[i][k]+f[i][j]);
                        f[i][j]=min(f[i][j],f[i][k]+f[j][k]);
                    }
                }
            }
            if (ans==inf) cout<<-1<<endl;
            else cout<<ans<<endl;

     堆优化dijkstra:

    /*
        O(eloge)堆优化dj算法,在n的数量级>=1e5时必须采用这种堆优化+邻接表方式 
    */
    struct node{
        int p, w;
        node(int a, int b):p(a), w(b){}
        bool operator< (const node& b) const
        {
            return w > b.w;
        }
    };
    vector<node> g[N];
    priority_queue<node> sup;
    void dijkstra(int start)
    {
        memset(dis, 0x3f, sizeof(dis));
        dis[start] = 0; pre[start] = start;
        sup.push(node(start, 0));
        while (!sup.empty())
        {
            node front = sup.top();
            sup.pop();  int tempv = front.p;
            if (visit[tempv]) continue;
            visit[tempv] = true;
            for (int i = 0; i < g[tempv].size(); i++)
            {
                int p = g[tempv][i].p;
                if (!visit[p] && dis[tempv]+g[tempv][i].w < dis[p])
                {
                    dis[p] = dis[tempv]+g[tempv][i].w;
                    pre[p] = tempv;
                    sup.push(node(p, dis[p]));
                }
            }
        }
    }

    参考:

    https://blog.csdn.net/j___t/article/details/82714139

    https://blog.csdn.net/xiazdong/article/details/8193680

  • 相关阅读:
    APS系统如何落地?用户实际痛点解析!
    供应链如何优化?高级排程系统为其运算
    不懂APS系统?十个问答让你对APS瞬间明明白白
    智能制造主战场在哪?数字化车间建设尤为重要
    中国制造转型的关键在哪里?智能制造点亮发展明灯
    你家的APS系统有这些功能吗?排程系统功能盘点
    微软正开发Office Reader和Office Lens
    C#的3DES加密解密算法
    如何在SharePoint2010中创建自定义电子邮件警报处理程序
    规划SharePoint2010的管理员密码更改
  • 原文地址:https://www.cnblogs.com/-ifrush/p/11456614.html
Copyright © 2011-2022 走看看