最短路模板 - Floyd / Dijkstra

Floyd算法:

写得很好的博客:最短路径问题---Floyd算法详解

算法的特点: 

  弗洛伊德算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图无向图负权(但不可存在负权回路)的最短路径问题,同时也被用于计算有向图的传递闭包。

算法的思路:

  通过Floyd计算图G=(V,E)中各个顶点的最短路径时,需要引入两个矩阵,矩阵S中的元素a[i][j]表示顶点i(第i个顶点)到顶点j(第j个顶点)的距离。矩阵P中的元素b[i][j],表示顶点i到顶点j经过了b[i][j]记录的值所表示的顶点。

  假设图G中顶点个数为N,则需要对矩阵D和矩阵P进行N次更新。初始时,矩阵D中顶点a[i][j]的距离为顶点i到顶点j的权值;如果i和j不相邻,则a[i][j]=∞,矩阵P的值为顶点b[i][j]的j的值。 接下来开始,对矩阵D进行N次更新。第1次更新时,如果”a[i][j]的距离” > “a[i][0]+a[0][j]”(a[i][0]+a[0][j]表示”i与j之间经过第1个顶点的距离”),则更新a[i][j]为”a[i][0]+a[0][j]”,更新b[i][j]=b[i][0]。 同理,第k次更新时,如果”a[i][j]的距离” > “a[i][k-1]+a[k-1][j]”,则更新a[i][j]为”a[i][k-1]+a[k-1][j]”,b[i][j]=b[i][k-1]。更新N次之后,操作完成!

  

  代码很短耶 一会都可以背下来了。时间复杂度为O(n^3)

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int INF = 0x3f3f3f;
 6 
 7 int ma[105][105], n, m;
 8 void floyd()
 9 {
10     for(int k = 1; k <= n; k++)
11         for(int i = 1; i <= n; i++)
12             for(int j = 1; j <= n; j++)
13                 ma[i][j] = min(ma[i][j],ma[i][k]+ma[k][j]);
14 }
15 int main()
16 {
17     while(cin >> n >> m && n && m){
18         memset(ma,INF,sizeof(ma));
19         for(int a,b,c,i = 0; i < m; i++){
20             cin >> a >> b >> c;
21             ma[a][b] = ma[b][a] = min(ma[a][b],c);
22         }
23         floyd();
24         cout << ma[1][n] << endl;
25     }
26     return 0;
27 }

 

 

 

Dijkstra算法:

写得很好的博客:Dijkstra 最短路算法

Dijkstra算法是处理单源最短路径的有效算法,但它局限于边的权值非负的情况,若图中出现权值为负的边,Dijkstra算法就会失效,求出的最短路径就可能是错的

/*可以输入以下数据进行验证第一行两个整数 n m。n 表示顶点个数(顶点编号为 1~n),m 表示边的条数。接下来 m 行表示,每行有 3 个数 x y z。表示顶点 x 到顶点 y 边的权值为 z。
6 9
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4
运行结果是
0 1 8 4 13 17
时间复杂度:O(N^2)
*/
#include<iostream>
#include<algorithm>
using namespace std;
const int INF = 0x3f3f3f;

int main()
{
    int n, m;
    int e[10][10], dis[10], book[10];
    cin >> n >> m;
    //初始化
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            if(i == j) e[i][j] = 0;
            else e[i][j] = INF;
    //读边
    for(int a,b,c,i = 1; i <= m; i++){
        cin >> a >> b >> c;
        e[a][b] = c;
    }
    //dis初始化
    for(int i = 1; i <= n; i++) dis[i] = e[1][i];
    //book初始化
    for(int i = 1; i <= n; i++) book[i] = 0;
    book[1] = 1;   //从点1开

    //Dijkstra:
    int minn, u;
    for(int i = 1; i <= n-1; i++){
        //先找离1最近的点:
        minn = INF;
        for(int j = 1; j <= n; j++)
            if(book[j] == 0 && dis[j] < minn){
                minn = dis[j];
                u = j;
        }
        book[u] = 1;
        for(int v = 1; v <= n; v++)
            if(e[u][v] < INF){
                if(dis[v] > dis[u]+e[u][v])
                    dis[v] = dis[u]+e[u][v];
        }
    }

    //输出点1到每条边的距离:
    for(int i = 1; i <= n; i++)
        cout << dis[i] << " ";
    return 0;
}

 

 

我jio得  大佬们都已经写得很好啦。还有补充的,以后有了再加。

还有几个其他的最短路算法

未完待续.......

posted @ 2018-08-30 14:13  愉也  阅读(491)  评论(0编辑  收藏  举报