最短路径 三种算法

Dijkstra算法(单源无负权图)


//适用于边权为正的情况,单源最短路问题
//时间复杂度为O(V*V+E)
//算法思路:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了)
//不断的维护一个dis数组,最后得到的dis数组中dis[i]就是源点到图中节点i的最短路径的长度
//记录vis数组判断当前点是否访问过

int mp[n][n],dis[n],vis[n];
void init()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j)
                mp[i][j]=0;
            else
                mp[i][j]=INF;
        }
    }
}
int djs(int st,int ed)
{
    for(int i=1;i<=n;i++)
    {
        dis[i]=mp[st][i];
        vis[i]=0;
    }
    vis[st]=1;
    for(int i=1;i<n;i++)
    {
        int minl=INF;
        int next=-1;   //确定下一个点
        for(int j=1;j<=n;j++)
        {
            if(vis[j]==0&&dis[j]<minn)
            {
                minl=dis[j];
                next=j;
            }
        }
        if(next==-1)   //当前已不存在点
            continue;
        vis[next]=1;
        for(int j=1;j<=n;j++)
        {
            if(vis[j]==0)                                  //vis[j]=1已为最短路径
                dis[j]=min(dis[j],dis[next]+mp[next][j]);  //以next为中间点进行松弛
        }
    }
    return dis[ed];
}

SPFA,Bellman-Ford的队列优化(单源有负权图)

//玄学时间复杂度,O(E)-O(VE)之间
//假设有一个点刚刚被优化了,我们可以很明显的发现,针对这条边,  也就只有这条边的出边上的终点才可以继续被优化
//这就给了我们启示,  其实我们可以再维护一个队列,一个点如果被优化过了,那么就进队列。

int n,m;
int mp[n][n],dis[n],vis[n];
void init()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j)
                mp[i][j]=0;
            else
                mp[i][j]=INF;
        }
    }
}
int spfa(int st,int ed)
{
    for(int i=1;i<=n;i++)
    {
        dis[i]=INF;
        vis[i]=0;
    }
    dis[st]=0;
    queue<int>q;
    q.push(st);
    vis[st]=1;
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        vis[now]=0;
        for(int i=1;i<=n;i++)
        {
            if(dis[i]>dis[now]+mp[now][i])
            {
                dis[i]=dis[now]+mp[now][i];
                if(vis[i]==0)
                {
                    q.push(i);
                    vis[i]=1;
                }
            }
        }
    }
    return dis[ed];
}

Floyd算法(多源无负权图)

//通过邻接矩阵跑出所有点之间的最短路,时间复杂度O(n^3),空间复杂度O(n^2)
//d[i][j]表示i到j的最短路径长度
//初始化:d[i][i]=0,点到点有路按正常权值初始化,其余为INF

#include<bits/stdc++.h>
#define INF 1e9
using namespace std;
int mp[105][105],dis[105][105];
int n,m;
void init()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j)
              dis[i][j]=0;
            else
              dis[i][j]=INF;
        }
    }

}
void Floyd()
{
    for(int k=1;k<=n;k++)//枚举以k为中间点的所有点的最短路
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
              dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
        }
    }
}
int main()
{
    int u,v,d;
    scanf("%d%d",&n,&m);
    init();
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&u,&v,&d);
        mp[u][v]=d;
        mp[v][u]=d'
    }
    scanf("%d%d",&s,&e);
    Floyd();
    printf("%d\n",dis[s][e]);
}

猜你喜欢

转载自blog.csdn.net/zcmu_2024/article/details/81162363