Алгоритм Дейкстры кратчайшего пути с одним источником и алгоритм Флойда кратчайшего пути с несколькими источниками, код C++

  1. Независимо от того, является ли это ориентированным графом или нет, единственная разница заключается в том, является ли матрица смежности симметричной матрицей, что не влияет на алгоритм
  2. Вес ребра не может быть отрицательным

Алгоритм Дейкстры по кратчайшему пути из одного источника

Можно получить кратчайший путь от одного узла src ко всем узлам
Найти кратчайший путь каждого узла в неубывающем порядке

/**维护直到flag全部为true
 * flag :是否已经找到最短路, 初始化全部false
 * dist :目前的最短距离 ,初始化全部正无穷INT32_MAX
 * path :最短路径的上一个节点, 初始化全部-1
 * 三个数组
 * */
int Dijkstra(int src, int dest, vector<int> &dist, vector<int> &path, vector<vector<int>> &MAT)
{
    
    
    int N = MAT.size();
    if (src < 0 || src >= N)
    {
    
    
        cout << "src不在节点0 - (N-1)之间" << endl;
        return -1;
    }
    vector<bool> flag(N, false); //标记找到最短路的节点
    //初始化
    for (int i = 0; i < N; i++)
    {
    
    
        if (MAT[src][i] != 0)
        {
    
    
            dist[i] = MAT[src][i];
            path[i] = src;
        }
    }
    dist[src] = 0;
    flag[src] = true;

    int min_v = -1;
    int min_dis = INT32_MAX;
    while (1)
    {
    
    
        min_v = -1;
        min_dis = INT32_MAX;
        //没有找到最短路的flag[i]=false中最小的距离,已经是最短距离了
        for (int i = 0; i < N; i++)
        {
    
    
            if (!flag[i])
            {
    
    
                if (dist[i] < min_dis) //要带 = 吗????
                {
    
    
                    min_dis = dist[i];
                    min_v = i;
                }
            }
        }
        //出口,都找到最短路了
        if (min_v == -1)
            break;

        for (int i = 0; i < N; i++)
        {
    
    
            if (MAT[min_v][i] != 0) //有直接相连边
            {
    
    
                if (dist[min_v] + MAT[min_v][i] < dist[i]) //更新路径
                {
    
    
                    dist[i] = dist[min_v] + MAT[min_v][i];
                    path[i] = min_v;
                }
            }
        }
        flag[min_v] = true;
    }

    //下面这部分只是输出信息了,要不要无所谓
    {
    
    
    cout << src << "-" << dest << "最短路径长度为: " << dist[dest] << endl;
    cout<<"路径为: "<<endl;
    stack<int> PATH;
    int id = dest;
    PATH.push(dest);
    while (path[id] != -1)
    {
    
    
        PATH.push(path[id]);
        id = path[id];
    }
    while (!PATH.empty())
    {
    
    
        cout << PATH.top() << " ";
        PATH.pop();
    }
    cout << endl;
    }

    return dist[dest];
}

Алгоритм Флойда кратчайшего пути с несколькими источниками

Найдите кратчайший путь между всеми узлами

//初始化距离矩阵DIST和MAT差不多,对角元素0(自己到自己最短距离),有直接相连的节点初始化为MAT[i][j],没有直接相连的初始化为正无穷INT32_MAX
//path全部是-1
void Floyd(vector<vector<int>>& DIST, vector<vector<int>>& path, vector<vector<int>>& MAT)
{
    
    
    int N=MAT.size();
    for(int k=0;k<N;k++)
    {
    
    
        for(int i=0;i<N;i++)
        {
    
    
            for(int j=0;j<N;j++)
            {
    
    
                if(DIST[i][k]+DIST[k][j] >0 && DIST[i][k]+DIST[k][j]<DIST[i][j]) //DIST[i][k]+DIST[k][j] >0 是因为,但凡有一个是INT32_MAX,结果就是小于0的
                {
    
    
                    DIST[i][j]=DIST[i][k]+DIST[k][j];
                    path[i][j]=k;
                }
            }
        }
    }
}

пример:

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

//单源最短路
int Dijkstra(int src, int dest, vector<int> &dist, vector<int> &path, vector<vector<int>> &MAT);
//多源最短路
void Floyd(vector<vector<int>>& DIST, vector<vector<int>>& path, vector<vector<int>>& MAT);
void print_path(int src, int dest, vector<vector<int>>& path);

int main()
{
    
    
    vector<vector<int>> MAT = {
    
    {
    
    0, 2, 0, 3, 3, 0, 0},
                               {
    
    0, 0, 1, 2, 0, 0, 0},
                               {
    
    0, 0, 0, 1, 0, 0, 3},
                               {
    
    0, 0, 0, 0, 3, 5, 3},
                               {
    
    0, 0, 0, 0, 0, 2, 0},
                               {
    
    0, 0, 0, 0, 0, 0, 4},
                               {
    
    0, 0, 0, 0, 0, 0, 0}};

    int N = MAT.size();
    for (int i = 0; i < N; i++)
    {
    
    
        for (int j = i + 1; j < N; j++)
        {
    
    
            MAT[j][i] = MAT[i][j];  //对称矩阵
        }
    }

    //Dijkstra  单源最短路
    int src;
    cout << "输入src:";
    cin >> src;
    int dest;
    cout << "输入dest:";
    cin >> dest;
    vector<int> dist(N, INT32_MAX);
    vector<int> path(N, -1);
    Dijkstra(src, dest, dist, path, MAT);

    //Floyd  多源最短路
    //初始化距离矩阵DIST和MAT差不多,对角元素0(自己到自己最短距离),有直接相连的节点初始化为MAT[i][j],没有直接相连的初始化为正无穷INT32_MAX
    vector<vector<int>> DIST(N,vector<int>(N,INT32_MAX));
    for(int i=0;i<N;i++)
    {
    
    
        for(int j=0;j<N;j++)
        {
    
    
            if(i==j)
            {
    
    
                DIST[i][j]=0;
            }
            else if(MAT[i][j]!=0)
            {
    
    
                DIST[i][j]=MAT[i][j];
            }
        }
    }
    vector<vector<int>> floyd_path(N,vector<int>(N,-1));

    Floyd(DIST,floyd_path, MAT);
    // for(int i=0;i<N;i++)
    // {
    
    
    //     for(int j=0;j<N;j++)
    //     {
    
    
    //         cout<<DIST[i][j]<<" ";
    //     }
    //     cout<<endl;
    // }
    // cout<<endl;
    // for(int i=0;i<N;i++)
    // {
    
    
    //     for(int j=0;j<N;j++)
    //     {
    
    
    //         cout<<floyd_path[i][j]<<" ";
    //     }
    //     cout<<endl;
    // }
    cout<<endl;
    cout<<src<<"-"<<dest<<"最短路径距离: "<<DIST[src][dest]<<endl;
    cout<<"路径为:"<<endl;
    print_path(src,dest,floyd_path);cout<<dest<<endl;

    return 0;
}

/**
 * 维护直到flag全部为true
 * flag :是否已经找到最短路, 初始化全部false
 * dist :目前的最短距离 ,初始化全部正无穷INT32_MAX
 * path :最短路径的上一个节点, 初始化全部-1
 * 三个数组
 * */
int Dijkstra(int src, int dest, vector<int> &dist, vector<int> &path, vector<vector<int>> &MAT)
{
    
    
    int N = MAT.size();
    // cout<<"N = "<<N<<endl;
    if (src < 0 || src >= N)
    {
    
    
        cout << "src不在节点0 - (N-1)之间" << endl;
        return -1;
    }
    vector<bool> flag(N, false); //标记找到最短路的节点
    //初始化
    for (int i = 0; i < N; i++)
    {
    
    
        if (MAT[src][i] != 0)
        {
    
    
            dist[i] = MAT[src][i];
            path[i] = src;
        }
    }
    dist[src] = 0;
    flag[src] = true;

    int min_v = -1;
    int min_dis = INT32_MAX;
    while (1)
    {
    
    
        min_v = -1;
        min_dis = INT32_MAX;
        //没有找到最短路的flag[i]=false中最小的距离,已经是最短距离了
        for (int i = 0; i < N; i++)
        {
    
    
            if (!flag[i])
            {
    
    
                if (dist[i] < min_dis) //要带 = 吗????
                {
    
    
                    min_dis = dist[i];
                    min_v = i;
                }
            }
        }
        //出口,都找到最短路了
        if (min_v == -1)
            break;

        for (int i = 0; i < N; i++)
        {
    
    
            if (MAT[min_v][i] != 0) //有直接相连边
            {
    
    
                if (dist[min_v] + MAT[min_v][i] < dist[i]) //更新路径
                {
    
    
                    dist[i] = dist[min_v] + MAT[min_v][i];
                    path[i] = min_v;
                }
            }
        }
        flag[min_v] = true;
    }

    //下面只是输出信息了,要不要无所谓
    cout << src << "-" << dest << "最短路径长度为: " << dist[dest] << endl;
    cout<<"路径为: "<<endl;
    stack<int> PATH;
    int id = dest;
    PATH.push(dest);
    while (path[id] != -1)
    {
    
    
        PATH.push(path[id]);
        id = path[id];
    }
    while (!PATH.empty())
    {
    
    
        cout << PATH.top() << " ";
        PATH.pop();
    }
    cout << endl;

    return dist[dest];
}

//初始化距离矩阵DIST和MAT差不多,对角元素0(自己到自己最短距离),有直接相连的节点初始化为MAT[i][j],没有直接相连的初始化为正无穷INT32_MAX
//path全部是-1
void Floyd(vector<vector<int>>& DIST, vector<vector<int>>& path, vector<vector<int>>& MAT)
{
    
    
    int N=MAT.size();
    for(int k=0;k<N;k++)
    {
    
    
        for(int i=0;i<N;i++)
        {
    
    
            for(int j=0;j<N;j++)
            {
    
    
                if(DIST[i][k]+DIST[k][j] >0 && DIST[i][k]+DIST[k][j]<DIST[i][j]) //DIST[i][k]+DIST[k][j] >0 是因为,但凡有一个是INT32_MAX,结果就是小于0的
                {
    
    
                    DIST[i][j]=DIST[i][k]+DIST[k][j];
                    path[i][j]=k;
                }
            }
        }
    }
}

void print_path(int src, int dest, vector<vector<int>>& path)
{
    
    
    if(path[src][dest]==-1) //中间谁都不隔
    {
    
    
        cout<<src<<" ";
        return;
    }
    int k=path[src][dest];//中间经过k
    print_path(src,k,path);
    print_path(k,dest,path);
}

Supongo que te gusta

Origin blog.csdn.net/qq_41253960/article/details/124797948
Recomendado
Clasificación