Dijkstra、Bellman-ford

1.Dijkstra邻接矩阵实现(时间少)

  • 时间复杂度 O(n²)
  • 空间复杂度 O(n²)
  • 不能出现负权边。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
int map[110][110];//这就是map数组,存储图
int dist[10010];//dist数组,存储距离
int book[10010];//book[i]代表这个点有没有被当做源点去搜索过,1为有,0为没有。这样就不会重复搜索了。
int n,m;
int path[110];//存路径 
void dijkstra(int x,int y)//参数是源点编号
{
    memset(dist,88,sizeof(dist));//把dist数组附最大值(88不是十进制的88,其实很大)
    int start=x;//先从源点搜索
    book[start]=1;//标记源点已经搜索过
    for(int i=1;i<=n;i++)
    {
        dist[i]=min(dist[i],map[start][i]);//先更新一遍
    }
    int k=0;
    for(int i=1;i<=n-1;i++)
    {
        int minn=9999999;
        for(int j=1;j<=n;j++)
            if(book[j]==0 && minn>dist[j])
            {
                minn=dist[j];
                start=j;//找到离源点最近的点,然后把编号记录下来,用于搜索。
            }
        book[start]=1;     
        for(int j=1;j<=n;j++)
        {
        	if(dist[start]+map[start][j]<dist[j]) 
			{	
				if(j==y)//存路径,只存x到y的 
				{
					path[k]=start;
					k++;
				}
			
				dist[j]=dist[start]+map[start][j];//存距离 
			}
        }
            //dist[j]=min(dist[j],dist[start]+map[start][j]);//以新的点来更新dist。
    }
}
void outpath(int x,int y)
{
	cout<<x<<"->";
    for(int i=0;path[i]!=0;i++)
        cout<<path[i]<<"->";
	cout<<y<<endl; 
}
int main()
{
    cin>>n>>m;//n个点,m个边 
    memset(map,88,sizeof(map));
    for(int i=1;i<=m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        map[a][b]=c;//有向图 
        //map[a][b]=map[b][a]=c;//无向图 
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(i==j)
                map[i][j]=0;
    int x=4,y=3;//x起点,y终点  
    dijkstra(x,y);//以x为源点,计算x到所有点的最短距离 
    for(int i=1;i<=n;i++)
        cout<<dist[i]<<" ";	 
        cout<<endl; 
    outpath(x,y);
}

《Dijkstra、Bellman-ford》

输入

//点数,边数

//a点,b点,ab距离

4 8
1 2 2
1 3 6
1 4 4
2 3 3
3 1 7
3 4 1
4 1 5
4 3 12

输出

//4到所有点的最短距离 

//4到3的最短路径

5 7 10 05 7 10 0
4->1->2->3

2.Dijkstra邻接表实现(空间少)

  • 时间复杂度O(n*m)
  • 空间复杂度 O(m)
  • 不能出现负权边。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
int value[10010],to[10010],next[10010];
int head[10010],total;
int book[10010];
int dist[10010];
int n,m;
void adl(int a,int b,int c)
{
    total++;
    to[total]=b;
    value[total]=c;
    next[total]=head[a];
    head[a]=total;
}
void dijkstra(int u)
{
    memset(dist,88,sizeof(dist));
    memset(book,0,sizeof(book));
    dist[u]=0;
    for(int i=1;i<=n;i++)
    {
        int start=-1;
        for(int j=1;j<=n;j++)
            if(book[j]==0 && (dist[start]>dist[j] || start==-1))
                start=j;
        book[start]=1;
        for(int e=head[start];e;e=next[e])
            dist[to[e]]=min(dist[to[e]],dist[start]+value[e]);
    }
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        adl(a,b,c);
     } 
     dijkstra(1);
     for(int i=1;i<=n;i++)
         cout<<dist[i]<<" ";
}

输入同上

输出0 2 5 4

 

3.Bellman-ford

  • 时间复杂度O(n*m)
  • 空间复杂度 O(m)
  • 可以出现负权边。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
int dist[10010];
//origin[i]表示编号为i这条边的起点编号,如origin[4]=2
//destination[i]表示编号为i这条边的终点编号,如origin[5]=5
//value[i]表示编号为i这条边的权值,如value[3]=-6 
int origin[10010],destination[10010],value[10010];
int n,m;
void Bellman_ford(int a)
{
    memset(dist,88,sizeof(dist));//赋初始值
    dist[a]=0;
    for(int i=1;i<=n-1;i++)//更新n-1次
        for(int j=1;j<=m;j++)//更新每一条边
            dist[destination[j]]=min(dist[destination[j]],dist[origin[j]]+value[j]);//判断是否更新
 } 
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
        cin>>origin[i]>>destination[i]>>value[i];
    Bellman_ford(1);
    for(int i=1;i<=n;i++)
        cout<<dist[i]<<" "; 
}

输入输出同上

 

 

 

 

 

 

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/aaakkk_1996/article/details/82082770
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞