• Dijkstra 算法实现样例


    样例输入:
    6
    0 2 5
    0 3 30
    1 0 2
    1 4 8
    2 5 7
    2 1 15
    4 3 4
    5 3 10
    5 4 18
    -1 -1 -1

    样例输出:


    20 0->2->1
    5 0->2
    22 0->2->5->3
    28 0->2->1->4
    12 0->2->5

    #include <stdio.h>
    #include <string.h>
    #define INF    1000000    //无穷大
    #define MAXN 20        //顶点个数的最大值
    
    int n;                //顶点个数
    int Edge[MAXN][MAXN];    //邻接矩阵
    int S[MAXN];        //Dijkstra算法用到的3个数组
    int dist[MAXN];        //
    int path[MAXN];        //
    
    void Dijkstra( int v0 )    //求顶点v0到其他顶点的最短路径
    {
        int i, j, k;    //循环变量
        for( i=0; i<n; i++ )
        {
            dist[i] = Edge[v0][i];  S[i] = 0;
            if( i!=v0 && dist[i]<INF )  path[i] = v0;
            else path[i] = -1;
        }
        S[v0] = 1;  dist[v0] = 0;    //顶点v0加入到顶点集合S
        for( i=0; i<n-1; i++ )        //从顶点v确定n-1条最短路径
        {
            int min = INF, u = v0;
            
            //选择当前集合T中具有最短路径的顶点u
            for( j=0; j<n; j++ )
            {
                if( !S[j] && dist[j]<min )
                {
                    u=j;  min = dist[j];
                }
            }
            
            S[u] = 1;    //将顶点u加入到集合S,表示它的最短路径已求得
            
            for( k=0; k<n; k++ )    //修改T集合中顶点的dist和path数组元素值
            {
                if( !S[k] && Edge[u][k]<INF && dist[u] + Edge[u][k] < dist[k] )
                {
                    dist[k] = dist[u] + Edge[u][k];  path[k] = u;
                }
            }
        }
    }
    
    int main( )
    {
        int i, j;    //循环变量
        int u, v, w;    //边的起点和终点及权值
        scanf( "%d", &n );    //读入顶点个数n
        while( 1 )
        {
            scanf( "%d%d%d", &u, &v, &w );    //读入边的起点和终点
            if( u==-1 && v==-1 && w==-1 )  break;
            Edge[u][v] = w;    //构造邻接矩阵
        }
        for( i=0; i<n; i++ )
        {
            for( j=0; j<n; j++ )
            {
                if( i==j ) Edge[i][j] = 0;
                else if( Edge[i][j]==0 )  Edge[i][j] = INF;
            }
        }
        Dijkstra( 0 );    //求顶点0到其他顶点的最短路径
        int shortest[MAXN];    //输出最短路径上的各个顶点时存放各个顶点的序号
        for( i=1; i<n; i++ )
        {
            printf( "%d	", dist[i] );    //输出顶点0到顶点i的最短路径长度
            //以下代码用于输出顶点0到顶点i的最短路径
            memset( shortest, 0, sizeof(shortest) );
            int k = 0;    //k表示shortest数组中最后一个元素的下标
            shortest[k] = i;
            while( path[ shortest[k] ] != 0 )
            {
                k++; shortest[k] = path[ shortest[k-1] ];
            }
            k++; shortest[k] = 0;
            for( j=k; j>0; j-- )
                printf( "%d→", shortest[j] );
            printf( "%d
    ", shortest[0] );
        }
        return 0;
    }
    /* Dijkstra O(E * log E)
    INIT: 调用init(nv, ne)读入边并初始化;
    CALL: dijkstra(n, src); dist[i]为src到i的最短距离 */
    int cost[E], dist[V];
    int e, pnt[E], nxt[E], head[V], prev[V], vis[V];
    struct qnode {
        int v;
        int c;
        qnode(int vv = 0, int cc = 0) : v(vv), c(cc) {}
        bool operator<(const qnode & r) const {return c > r.c;}
    };
    void dijkstra(int n, const int src) {
        qnode mv;
        int i, j, k, pre;
        priority_queue<qnode> que;
        vis[src] = 1;
        dist[src] = 0;
        que.push(qnode(src, 0));
        for (pre = src, i = 1; i < n; i++) {
            for (j = head[pre]; j != -1; j = nxt[j]) {
                k = pnt[j];
                if (vis[k] == 0 && dist[pre] + cost[j] < dist[k]) {
                    dist[k] = dist[pre] + cost[j];
                    que.push(qnode(pnt[j], dist[k]));
                    prev[k] = pre;
                }
            }
            while (!que.empty() && vis[que.top().v] == 1)
                que.pop();
            if (que.empty()) break;
            mv = que.top();
            que.pop();
            vis[pre = mv.v] = 1;
        }
    }
    inline void addedge(int u, int v, int c) {
        pnt[e] = v;
        cost[e] = c;
        nxt[e] = head[u];
        head[u] = e++;
    }
    void init(int nv, int ne) {
        int i, u, v;
        int c;
        e = 0;
        memset(head, -1, sizeof (head));
        memset(vis, 0, sizeof (vis));
        memset(prev, -1, sizeof (prev));
        for (i = 0; i < nv; i++) dist[i] = inf;
        for (i = 0; i < ne; ++i) {
            scanf("%d%d%d", &u, &v, &c); // %d: type of cost
            addedge(u, v, c); // vertex: 0 ~ n-1, 单向边,双向边时加两次即可
        }
    }
  • 相关阅读:
    python 04 list增删改查 迷途小书童
    xhtml+css符合标准的WEB设计
    在Ubuntu16.0.4安装hipcaffe
    简单使用OpenSSL生成密钥
    Ubuntu 16.04 集成安装Apache+PHP+Kerberos+LDAP+phpLDAPadmin
    Ubuntu 安装mysql & 自定义数据存储目录
    TestLink+Jenkins在Ubuntu16.04搭建集成测试环境
    Rancher 2.1平台搭建及使用
    JavaFX_homework1_pane
    linux 命令1 转
  • 原文地址:https://www.cnblogs.com/Deng1185246160/p/3223025.html
Copyright © 2020-2023  润新知