zoukankan      html  css  js  c++  java
  • POJ-图论-最短路模板(邻接矩阵)

    POJ-图论-最短路模板

    一、Floyd算法

    刚读入数据时,G为读入的图邻接矩阵,更新后,G[i][j]表示结点i到结点j的最短路径长度

    int G[N][N];//二维数组,其初始值即为该图的邻接矩阵

    1.init():初始化图邻接矩阵

    void init()
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                G[i][j] = -1;//初始化邻接矩阵,用-1代表无穷
            }
            G[i][i] = 0;//初始化,自己到自己的路径长度为0
        }
    }

    2.floyd():更新最短路径

    void floyd()
    {
        for (int k = 1; k <= n; k++)//从1至n循环k
        {
            for (int i = 1; i <= n; i++)
            {
                for (int j = 1; j <= n; j++)//遍历所有的i,j
                {
                    if (G[i][k] == -1 || G[k][j] == -1)continue;
                    if (G[i][j] == -1 || G[i][k] + G[k][j] < G[i][j])G[i][j] = G[i][k] + G[k][j];
                }
            }
        }
    }

    例 5.5 最短路 

    模板代码

    #include<cstdio>
    const int N = 105;
    int G[N][N];
    int n, m;
    
    void init()
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                G[i][j] = -1;//初始化为无穷
            }
        }
        for (int i = 1; i <= n; i++)G[i][i] = 0;//自己到自己距离是0
    }
    
    void floyd()
    {
        for (int k = 1; k <= n; k++)
        {
            for (int i = 1; i <= n; i++)
            {
                for (int j = 1; j <= n; j++)
                {
                    if (G[i][k] == -1 || G[k][j] == -1)continue;
                    else if (G[i][j] == -1 || G[i][j] > G[i][k] + G[k][j])G[i][j] = G[i][k] + G[k][j];
                }
            }
        }
    }
    
    int main()
    {
        while (scanf("%d%d", &n, &m) != EOF)
        {
            if (n == 0 && m == 0)break;
            init();
            int x, y, t;
            for (int i = 0; i < m; i++)
            {
                scanf("%d%d%d", &x, &y, &t);
                G[x][y] = G[y][x] = t;
            }
            floyd();
            printf("%d
    ", G[1][n]);
        }
        return 0;
    }

    二、Dijkstra算法

    G为图邻接矩阵,G[i][j]表示读入的i到j的距离,后面不再更新。d[]为距离数组,d[i]表示结点i到起点的最短距离。vis[N]为访问数组,记录各结点的访问情况。

    int G[N][N]; // 图邻接矩阵
    int d[N]; // 表示起点到各结点的最短距离
    bool vis[N] = { false }; // 表示各结点被访问过与否

    1.init():初始化邻接矩阵,到自身的距离为0

    void init() // 初始化
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                if (i == j) G[i][j] = 0;
                else G[i][j] = INF;
            }
        }
    }

    2.Dijkstra(int start):初始化d[]之后,进行n次循环,每次先确定与起点直接相连的距离最小结点u及其距离d[u],再更新起点到其他结点v的距离d[v]。

    void Dijkstra(int start)
    {
        for (int i = 1; i <= n; i++) d[i] = INF;//可达距离都初始化为无穷
        d[start] = 0; // 起初只有start结点可达
        for (int i = 1; i <= n; i++)
        {
            int u = -1; // 距离最近的结点u,初始化为-1
            int min = INF; // min存放最小的d[u],初始化为无穷
            for (int j = 1; j <= n; j++)//得到最近的点
            {
                if (vis[j] == false && d[j] < min)
                {
                    u = j; // 与起点直接相连的距离最小结点
                    min = d[j];
                }
            }
            if (u == -1) return; // 说明剩下的未被访问过的结点都是与起点不可达的
            vis[u] = true; // 设为已读
            for (int v = 1; v <= n; v++)//由新得到的点更新后面所有点
            {
                // 此处d[u]有一个相加操作,所以在设置很大整数时不能设置为0x7fffffff,会导致溢出
                if (vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]) d[v] = d[u] + G[u][v];
            }
        }
    }

     例 5.5 最短路 

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N = 105;
    const int INF = 0x3fffffff;
    int n, m;
    int G[N][N];
    int d[N];//起点到各点的距离
    bool vis[N] = { false };
    
    void init()
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                G[i][j] = INF;
            }
            G[i][i] = 0;
        }
        for (int i = 1; i <= n; i++)
        {
            d[i] = INF;
            vis[i] = false;
        }
    }
    
    void djkstra(int start)
    {
        d[start] = 0;
        for (int i = 1; i <= n; i++)//每次加入一个结点(这时连起点都还没加入)
        {
            int u = -1;//最近的结点
            int min = INF;//最近的距离值
            for (int j = 1; j <= n; j++)
            {
                if (vis[j] == false && d[j] < min)
                {
                    min = d[j];
                    u = j;
                }
            }
            if (u == -1)return;//无路可走
            vis[u] = true;
            for (int v = 1; v <= n; v++)//更新其他节点
            {
                if (vis[v] == false && G[u][v] != INF && d[v] > d[u] + G[u][v])d[v] = d[u] + G[u][v];
            }
        }
    }
    
    int main()
    {
        while (scanf("%d%d", &n, &m) != EOF)
        {
            if (n == 0 && m == 0)break;
            init();
            for (int i = 0; i < m; i++)
            {
                int a, b, t;
                scanf("%d%d%d", &a, &b, &t);
                G[a][b] = G[b][a] = t;
            }
            djkstra(1);
            printf("%d
    ", d[n]);
        }
        return 0;
    }
  • 相关阅读:
    Linux Shell for循环写法总结 皇星客栈
    关于adr指令的理解 皇星客栈
    lds linux下的通用链接脚本 皇星客栈
    2430实验点对点通信实验 皇星客栈
    #pragma vector 皇星客栈
    linux下firefox安装Adobe Flash Player插件 皇星客栈
    一个shell脚本引发的对于分号(;)和$#的使用说明(转载) 皇星客栈
    代码打开wince自带的wif配置窗口i
    C#数组的合并拆分
    Coding4Fun
  • 原文地址:https://www.cnblogs.com/yun-an/p/11104314.html
Copyright © 2011-2022 走看看