ACM模板 最短路径问题

最短路径

问题描述:最短路径问题是图论研究中的一个经典算法问题,旨在寻找图(由结点和路径组成的)中两结点之间的最短路径。算法具体的形式包括:

  • 确定起点的最短路径问题 - 即已知起始结点,求最短路径的问题。适合使用Dijkstra算法。
  • 确定终点的最短路径问题 - 与确定起点的问题相反,该问题是已知终结结点,求最短路径的问题。
  • 在无向图中该问题与确定起点的问题完全等同,在有向图中该问题等同于把所有路径方向反转的确定起点的问题。
  • 确定起点终点的最短路径问题 - 即已知起点和终点,求两结点之间的最短路径。
  • 全局最短路径问题 - 求图中所有的最短路径。适合使用Floyd-Warshall算法。
    源于维基百科;
    所以这里就分析给出两个模板,就是Dijkstra算法以及Floyd算法,其余算法请自行百度

DIjkstra算法

适用于已知起点,终点的最短路问题;
代码展示:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 999999;
int n, m, g[110][110], dis[110]; //n,m代表有n个点,m条路;g[a][b]就是a到b的长度
//的数组,dis表示最短距离,即起始点到i的最短距离
bool vis[110]; //标记数组,用来确定某个点是否被访问过,用int也可以,true代表已访问

int Dijkstra(int src, int des) //src起始点,des终止点
{
    int temp, k;                    //都是中间变量
    memset(vis, false, sizeof vis); //初始化
    for (int i = 1; i <= n; i++)    //初始化dis
    {
        dis[i] = (i == src ? 0 : g[src][i]);
    }
    vis[src] = true;
    for (int i = 1; i <= n; i++)
    {
        temp = maxn;                 //赋初始值
        for (int j = 1; j <= n; j++) //这个循环主要用来找当前情况下,下一步走哪最短
        {
            if (!vis[j] && temp > dis[j])
                temp = dis[k = j];
        }
        if (temp == maxn) //说明找不到了,就退出
            break;
        vis[k] = true; //找到了k
        for (int j = 1; j <= n; j++)
        {
            if (!vis[j] && dis[j] > dis[k] + g[k][j]) //更新dis
                dis[j] = dis[k] + g[k][j];
        }
    }
    return dis[des]; //dis这时就表示了起始点到i点的最短距离
}

int main()
{
    int ans;
    while (cin >> n >> m && (n + m)) //题目要求n+m为零时结束
    {
        memset(g, maxn, sizeof g);
        int a, b, c;
        while (m--)
        {
            cin >> a >> b >> c;
            if (c < g[a][b]) //无向路,且加个判断是为了使平行路只取最小的
                g[a][b] = g[b][a] = c;
        }
        ans = Dijkstra(1, n);
        cout << ans << endl;
    }
    return 0;
}

Floyd算法

适合于全局线下求最短路
代码展示:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 999999;
int n, m, g[110][110]; //g[a][b]代表着a到b的最短路径

void Floyd()
{
    for (int k = 1; k <= n; k++)
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                g[i][j] = min(g[i][j], g[i][k] + g[k][j]);//暴力
            }
        }
    }
}
int main()
{
    while (cin >> n >> m && (n + m))
    {
        memset(g, maxn, sizeof g);
        int a, b, c;
        while (m--)
        {
            cin >> a >> b >> c;
            if (c < g[a][b])
                g[a][b] = g[b][a] = c;
        }
        Floyd();
        cout << g[1][n] << endl;
    }
    return 0;
}

创作不易,点个赞支持一下呗!
在这里插入图片描述

发布了47 篇原创文章 · 获赞 24 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/zmx2473162621/article/details/104065700
今日推荐