最短路算法模板合集(Dijkstar,Dijkstar(优先队列优化), 多源最短路Floyd)

再开始前我们先普及一下简单的图论知识

图的保存:

1.邻接矩阵。 G[maxn][maxn];

2.邻接表

邻接表我们有两种方式

(1)vector< Node > G[maxn];

这个是之前就定义了图的大小了,再下面使用的时候就不用对图的大小进行申请了, 但是因为是直接申请了大小

要对图进行初始化,因此可能在某些题目中这样使用的话会超时

(2)vector< vector<Node> > G;

这个是未定义大小,但是在使用之前要对其的大小内存进行申请。

 G.resize(n+1);

 

Dijkstra's Algorithm

算法思想:

1.从源点出发源点所有能一步到达的点的距离更新,然后从除源点外的所有点之中找出距离源点最近的点。

2.然后更新我们之前所找到的最短路点所有连接的点,但是要求这个点未曾被当做最短点处理过

3.重复上述操作n次。

 

单源最短路 我们还可以对他进行优先队列优化下面是以HDU2544为模板的用Dijkstra's Algorithm 

 

邻接矩阵版,不用优先队列优化

#include <iostream>

#include <cstdlib>

#include <cstdio>

#include <algorithm>

#include <vector>

#include <queue>

using namespace std;

#define INF 0xfffffff

#define maxn 1002



int G[maxn][maxn];//保存图

int dist[maxn];//表示从起点到第i点的距离

bool vis[maxn];//判断这个点是否被参观过

int m, n;//边数 m   顶点数 n



void Init()

{

    for(int i=0; i<=n; i++)

    {

        vis[i] = false;

        dist[i] = INF;

        for(int j=0; j<=i; j++)

            G[i][j] = G[j][i] =  INF;

    }

}

int Dij(int Star,int End)//起点 --- 终点

{

    dist[Star] = 0;

    for(int i=1; i<=n; i++)

    {

        int index = 0, Min = INF;

        for(int j=1; j<=n; j++)

        {

            if( !vis[j] && Min > dist[j] )//找出没有被参观过,并且距离起点最近的点

                Min = dist[j], index = j;

        }



        vis[index] = true;



        for(int j=1; j<=n; j++)//更新所有未曾到达的点距离,使之成为最近的点

        {

            if( !vis[j] && dist[j] >  dist[index] + G[index][j] )

                dist[j] = dist[index] + G[index][j];

        }

    }



    return dist[End];



}



int main()

{

    while(cin >> n >> m, m + n)

    {

        Init();



        int a, b , c;



        for(int i=0; i<m; i++)

        {

            cin >> a >> b >> c;

            G[a][b] = min(G[a][b], c);

            G[b][a] = G[a][b];

        }



        int ans = Dij(1,n);



        cout << ans << endl;

    }

    return 0;

}

  接下来是邻接表版,用到了优先队列优化

 1 #include <iostream>

 2 #include <cmath>

 3 #include <cstring>

 4 #include <cstdlib>

 5 #include <cstdio>

 6 #include <algorithm>

 7 #include <vector>

 8 #include <queue>

 9 using namespace std;

10 #define INF 0xfffffff

11 #define maxn 1002

12 

13 struct Node

14 {

15     int e;

16     int w;

17     friend bool operator < (Node A, Node B)

18     {

19         return  A.w > B.w;

20     }

21 };

22 

23 bool vis[maxn];

24 

25 int m, n;

26 vector< vector<Node> > G;

27 

28 int Dij(int Star,int End)

29 {

30     Node P, Pn;

31     P.e = Star;

32     P.w = 0;

33 

34     priority_queue<Node> Q;

35 

36     Q.push(P);

37 

38     while( !Q.empty() )

39     {

40         P = Q.top();

41         Q.pop();

42 

43         if( vis[P.e] )

44             continue;

45 

46         vis[P.e] = true;

47 

48         if( P.e == End )

49             return P.w;

50 

51         int len = G[P.e].size();

52 

53         for(int i=0; i< len; i++)

54         {

55             Pn.e = G[P.e][i].e;

56             Pn.w = G[P.e][i].w + P.w;

57 

58             if( !vis[Pn.e] )

59                 Q.push(Pn);

60         }

61     }

62     return -1;

63 }

64 

65 int main()

66 {

67     Node P;

68     while(cin >> n >> m, m+n)

69     {

70         G.clear();

71         G.resize(n+1);

72 

73         memset(vis,false,sizeof(vis));

74 

75         for(int i=0; i<m; i++)

76         {

77             int a, b, c;

78             cin >> a >> b >> c;

79             P.e = b;

80             P.w = c;

81             G[a].push_back(P);

82             P.e = a;

83             G[b].push_back(P);

84         }

85 

86         int ans = Dij(1,n);

87 

88         cout << ans << endl;

89     }

90     return 0;

91 }

 

下面是Floyd算法

Floyd是求多源最短路, 即可以求出所有点对之间的最短路

这个算法就只要注意两点就行了,初始化的时候 G[i][i] = 0, 其他的初始化为INF

#include <iostream>

#include <cmath>

#include <cstring>

#include <cstdlib>

#include <cstdio>

#include <algorithm>

#include <vector>

#include <queue>

using namespace std;

#define INF 0xfffffff

#define maxn 1002



int G[maxn][maxn];

int dist[maxn][maxn];

int m, n;



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]);

            }

        }

    }

}

void Init()

{

    for(int i=0; i<=n; i++)

    {

        G[i][i] = 0;

        for(int j=0; j<i; j++)

            G[i][j] = G[j][i] = INF;

    }

}



int main()

{

    while(cin >> n >> m, m+n)

    {

        Init();

        for(int i=0; i<m; i++)

        {

            int a, b, c;

            cin >> a >> b >> c;

            G[a][b] = min(G[a][b],c);

            G[b][a] = G[a][b];

        }



        Floyd();



        cout << G[1][n] << endl;

    }

    return 0;

}

 

你可能感兴趣的:(floyd)