最短路径:Dijkstra,Bellman,SPFA,Floyd该算法的实施

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzQ4NzA1MQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="900" height="500" >

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzQ4NzA1MQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="900" height="400" >

</pre><pre name="code" class="cpp">

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>

using namespace std;

const int INF = 0x3f3f3f3f;//无穷大
const int maxn = 20;//顶点个数的最大值
int n;//顶点个数
int edge[maxn][maxn];//邻接矩阵
//Dijkstra算法用到的3个数组
int s[maxn];//记录顶点是否在集合中
int dist[maxn];//记录路径的权值
int path[maxn];//记录路径

void Dijkstra( int v0 )//求v0到其它点的最短路径
{
    int i, j, k;//循环变量
    for(i=0; i<n; i++)
    {
        dist[i] = edge[v0][i];
        s[i] = 0;
        if( i!=v0 && dist[i]<INF )
            path[i] = v0;
        else
            path[i] = -1;
    }
    s[v0] = 1; dist[v0] = 0;//顶点v0增加顶点集合s
    for(i=0; i<n-1; i++)//从顶点v0确定n-1条最短路径
    {
        int min = INF, u = v0;
        //选择当前集合T中具有最短路径的顶点u
        for(j=0; j<n; j++)
        {
            if( !s[j] && dist[j]<min )
            {
                u = j;
                min = dist[j];
            }
        }
        s[u] = 1;//将顶点u增加集合s。表示它的最短路径已求得
        //改动T集合中顶点的dist和path数组元素
        for(k=0; k<n; k++)
        {
            if( !s[k] && edge[u][k]<INF && dist[u]+edge[u][k]<dist[k] )
                {
                    dist[k] = dist[u] + edge[u][k];
                    path[k] = u;
                }
        }
    }
}

int main()
{
    int i, j;//循环变量
    int u, v, w;//边的起点和终点以及权值
    scanf("%d", &n);//读入顶点个数n
    while(1)
    {
        scanf("%d%d%d", &u, &v, &w);
        if( u==-1 && v==-1 && w==-1 )
            break;
        edge[u][v] = w;//构建邻接矩阵
    }
    for(i=0; i<n; i++)
    {
        for(j=0; j<n; j++)
        {
            if( i==j )
                edge[i][j] = 0;
            else if( edge[i][j] == 0 )
                edge[i][j] = INF;
        }
    }
    Dijkstra(0);//求顶点0到其它顶点的最短路径
    int shortest[maxn];//输出最短路径上的各个顶点时存放各个顶点的序号
    for(i=1; i<n; i++)
    {
        printf("%d\t", dist[i]);//输出顶点0到顶点i的最短路径长度
        //下面代码用于输出顶点0带顶点i的最短路径
        memset( shortest, 0, sizeof(shortest) );
        int k = 0;//k表示shorttest数组中最后一个元素的下标
        shortest[k] = i;
        while( path[ shortest[k] ]!=0 )
        {
            k++;
            shortest[k] = path[shortest[k-1]];
            //printf("%d ", k);
        }
        k++; shortest[k] = 0;
        //printf("%d", k);
        for(j=k; j>0; j--)
            printf("%d--", shortest[j]);
        printf("%d\n", shortest[0]);
    }

    return 0;
}

Bellman:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>

using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 8;
int edge[maxn][maxn];
int dist[maxn];
int path[maxn];
int n;

void Bellman(int v0)
{
    int i, j, k, u;
    for(i=0; i<n; i++)
    {
        dist[i] = edge[v0][i];
        if( i!=v0 && dist[i] < INF )
            path[i] = v0;
        else
            path[i] = -1;
    }
    for(k=2; k<n; k++)
    {
        for(u=0; u<n; u++)
        {
            if( u!=v0 )
            {
                for( j=0; j<n; j++ )
                {
                    if( edge[j][u] < INF && dist[j] + edge[j][u] < dist[u] )
                    {
                        dist[u] = dist[j] + edge[j][u];
                        path[u] = j;
                    }
                }
            }
        }
    }
}

int main()
{
    int i, j;
    int u, v, w;
    scanf("%d", &n);
    while( 1 )
    {
         scanf("%d%d%d", &u, &v, &w);
         if( u==-1 && v==-1 && w==-1 )
            break;
         edge[u][v] = w;
    }
    for(i=0; i<n; i++)
    {
        for(j=0; j<n; j++)
        {
            if( i==j )
                edge[i][j] = 0;
            else if( edge[i][j]==0 )
                edge[i][j] = INF;
        }
    }
    Bellman(0);
    int shortest[maxn];
    for(i=1; i<n; i++)
    {
        printf("%d\t", dist[i]);
        memset( shortest, 0, sizeof(shortest) );
        int k = 0;
        shortest[k] = i;
        while( path[shortest[k]]!=0 )
        {
            k++;
            shortest[k] = path[shortest[k-1]];
        }
        k++;
        shortest[k] = 0;
        for(j=k; j>0; j--)
            printf("%d--", shortest[j]);
        printf("%d\n", shortest[0]);
    }

    return 0;
}

SPFA:

#include <cstdio>
#include <cstring>
#include <queue>
#define INF  1000000  //无穷大
#define MAXN 10

using namespace std;

struct ArcNode
{
    int to;
    int weight;
    struct ArcNode *next;
};

queue<int> Q;  //队列中的结点为顶点序号
int n;   //顶点个数
ArcNode* List[MAXN];  //每一个顶点的边链表表头指针
int inq[MAXN];  //每一个顶点是否在队列中的标志
int dist[MAXN];  //
int path[MAXN]; //

void SPFA( int src )
{
    int i, u;  //u为队列头顶点序号
    ArcNode* temp;
    for( i=0; i<n; i++ )  //初始化
    {
        dist[i] = INF;
        path[i] = src;
        inq[i] = 0;
    }
    dist[src] = 0;
    path[src] = src;
    inq[src]++;
    Q.push( src );
    while( !Q.empty() )
    {
        u = Q.front( );
        Q.pop( );
        inq[u]--;
        temp = List[u];
        while( temp!=NULL )
        {
            int v = temp->to;

            if( dist[v] > dist[u] + temp->weight )
            {
                dist[v] = dist[u] + temp->weight;
                path[v] = u;
                if( !inq[v] )
                {
                    Q.push(v);
                    inq[v]++;
                }
            }
            temp = temp->next;
        }
    }
}

int main( )
{
    int i, j;  //循环变量
    int u, v, w;  //边的起点和终点及权值
    scanf( "%d", &n );  //读入顶点个数n
    memset( List, 0, sizeof(List) );
    ArcNode* temp;
    while( 1 )
    {
        scanf( "%d%d%d", &u, &v, &w ); //读入边的起点和终点
        if( u==-1 && v==-1 && w==-1 )    break;
        temp = new ArcNode;
        //构造邻接表
        temp->to = v;
        temp->weight = w;
        temp->next = NULL;
        if( List[u]==NULL )    List[u] = temp;
        else
        {
            temp->next = List[u];
            List[u] = temp;
        }
    }
    SPFA( 0 ); //求顶点0到其它顶点的最短路径
    for( j=0; j<n; j++ )  //释放边链表上各边结点所占用的存储空间
    {
        temp = List[j];
        while( temp!=NULL )
        {
            List[j] = temp->next;
            delete temp;
            temp = List[j];
        }
    }

    int shortest[MAXN];  //输出最短路径上的各个顶点时存放各个顶点的序号
    for( i=1; i<n; i++ )
    {
        printf( "%d\t", dist[i] );  //输出顶点0到顶点i的最短路径长度
        //下面代码用于输出顶点0到顶点i的最短路径
        memset( shortest, 0, sizeof(shortest) );
        int k = 0;  //k表示shortest数组中最后一个元素的下标
        shortest[k] = i;
        while( path[ shortest[k] ] != 0 )
        {
            k++;
            shortest[k] = path[ shortest[k-1] ];
        }
        k++;
        shortest[k] = 0;
        for( j=k; j>0; j-- )
            printf( "%d→", shortest[j] );
        printf( "%d\n", shortest[0] );
    }
    return 0;
}

Floyd:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>

using namespace std;
#define INF  1000000  //无穷大
#define MAXN 8

int n;   //顶点个数
int Edge[MAXN][MAXN];  //邻接矩阵
int A[MAXN][MAXN];    //
int path[MAXN][MAXN];  //

void Floyd( ) //假定图的邻接矩阵和顶点个数已经读进来了
{
    int i, j, k;
    for( i=0; i<n; i++ )
    {
        for( j=0; j<n; j++ )
        {
            A[i][j] = Edge[i][j]; //对a[ ][ ]初始化
            if( i!=j && A[i][j]<INF )    path[i][j] = i; //i到j有路径
            else path[i][j] = -1; //从i到j没有直接路径
        }
    }
//从A(-1)递推到A(0), A(1), ..., A(n-1),或者理解成依次将v0,v1,...,v(n-1)作为中间顶点
    for( k=0; k<n; k++ )
    {
        for( i=0; i<n; i++ )
        {
            for( j=0; j<n; j++ )
            {
                if( k==i || k==j )  continue;
                if( A[i][k] + A[k][j] < A[i][j] )
                {
                    A[i][j] = A[i][k] + A[k][j] ;
                    path[i][j] = path[k][j];
                }
            }
        }
    }
}

int main( )
{
    int i, j;  //循环变量
    int u, v, w;  //边的起点和终点及权值
    scanf( "%d", &n );  //读入顶点个数n
    for( i=0; i<n; i++ )  //设置邻接矩阵中每一个元素的初始值为INF
    {
        for( j=0; j<n; j++ )    Edge[i][j] = INF;
    }
    for( i=0; i<n; i++ )  //设置邻接矩阵中对角线上的元素值为0
    {
        Edge[i][i] = 0;
    }
    while( 1 )
    {
        scanf( "%d%d%d", &u, &v, &w ); //读入边的起点和终点
        if( u==-1 && v==-1 && w==-1 )    break;
        Edge[u][v] = w; //构造邻接矩阵
    }
    Floyd( ); //求各对顶点间的最短路径
    int shortest[MAXN]; //输出最短路径上的各个顶点时存放各个顶点的序号
    for( i=0; i<n; i++ )
    {
        for( j=0; j<n; j++ )
        {
            if( i==j )  continue; //跳过
            printf( "%d=>%d\t%d\t", i, j, A[i][j] );  //输出顶点i到顶点j的最短路径长度
            //下面代码用于输出顶点0到顶点i的最短路径
            memset( shortest, 0, sizeof(shortest) );
            int k = 0; //k表示shortest数组中最后一个元素的下标
            shortest[k] = j;
            while( path[i][ shortest[k] ] != i )
            {
                k++;
                shortest[k] = path[i][ shortest[k-1] ];
            }
            k++;
            shortest[k] = i;
            for( int t=k; t>0; t-- )
                printf( "%d→", shortest[t] );
            printf( "%d\n", shortest[0] );
        }
    }

    return 0;
}

版权声明:本文博主原创文章。博客,未经同意不得转载。

时间: 2024-10-17 02:28:55

最短路径:Dijkstra,Bellman,SPFA,Floyd该算法的实施的相关文章

四大算法解决最短路径问题(Dijkstra+Bellman-ford+SPFA+Floyd)

什么是最短路径问题? 简单来讲,就是用于计算一个节点到其他所有节点的最短路径. 单源最短路算法:已知起点,求到达其他点的最短路径. 常用算法:Dijkstra算法.Bellman-ford算法.SPFA算法 多源最短路算法:求任意两点之间的最短路径. 常用算法:floyd算法 单源最短路径——Dijkstra Dijkstra算法是经典的最短路径算法,用于计算一个节点到其他所有节点的最短路径. 主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 时间复杂度:O(n^2) 处理问题:单源.

最短路径-Dijkstra算法与Floyd算法

一.最短路径 ①在非网图中,最短路径是指两顶点之间经历的边数最少的路径. AE:1    ADE:2   ADCE:3   ABCE:3 ②在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径. AE:100   ADE:90   ADCE:60   ABCE:70 ③单源点最短路径问题 问题描述:给定带权有向图G=(V, E)和源点v∈V,求从v到G中其余各顶点的最短路径. 应用实例--计算机网络传输的问题:怎样找到一种最经济的方式,从一台计算机向网上所有其它计算机发送一条消息. ④每

最短路径Dijkstra算法和Floyd算法整理、

转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹

杭电1874-畅通工程续(最短路径,dijkstra,spfa,floyd)

畅通工程续 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 37458    Accepted Submission(s): 13826 Problem Description 某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行

dijkstra,SPFA,Floyd求最短路

Dijkstra: 裸的算法,O(n^2),使用邻接矩阵: 算法思想: 定义两个集合,一开始集合1只有一个源点,集合2有剩下的点. STEP1:在集合2中找一个到源点距离最近的顶点k:min{d[k]} STEP2:把顶点k加入集合1中,同时修改集合2中的剩余顶点j的d[j]是否经过k之后变短,若变短则修改d[j]; if d[k]+a[k,j]<d[j] then   d[j]=d[k]+a[k,j]; STEP3:重复STEP1,直到集合2为空为止. #include <iostream&

hdu1874 畅通project续 最短路 floyd或dijkstra或spfa

Problem Description 某省自从实行了非常多年的畅通project计划后.最终修建了非常多路.只是路多了也不好,每次要从一个城镇到还有一个城镇时,都有很多种道路方案能够选择.而某些方案要比还有一些方案行走的距离要短非常多.这让行人非常困扰. 如今,已知起点和终点.请你计算出要从起点到终点,最短须要行走多少距离. Input 本题目包括多组数据,请处理到文件结束. 每组数据第一行包括两个正整数N和M(0< N<200,0 < M<1000),分别代表现有城镇的数目和已

HDU 3790 最短路径问题(SPFA || Dijkstra )

题目链接 题意 : 中文题不详述. 思路 :无论是SPFA还是Dijkstra都在更新最短路的那个地方直接将花费更新了就行,还有别忘了判重边,话说因为忘了判重边WA了一次. 1 //3790 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #include <queue> 7 const int INF = 1 <

图-最短路径-Dijkstra及其变种

目录 最短路径 Dijkstra 算法 算法思想 具体实现 最短路径 Dijkstra+DFS 最短路径 最短路径问题: 给定任意的图G(V,E) 和起点 S,终点 T,如何求从 S 到 T 的最短路径. 解决最短路径的常用方法有 Dijkstra 算法 Bellman-Ford 算法 SPFA 算法 Floyd 算法 这里主要对 Dijkstra 算法及其变种进行总结. Dijkstra 算法 算法思想 Dijkstra 算法用来解决单源最短路径问题,即给定图 G 和起点 s,通过算法得到 S

hihoCoder - 1093 - 最短路径&#183;三:SPFA算法 (SPFA)

#1093 : 最短路径·三:SPFA算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 万圣节的晚上,小Hi和小Ho在吃过晚饭之后,来到了一个巨大的鬼屋! 鬼屋中一共有N个地点,分别编号为1..N,这N个地点之间互相有一些道路连通,两个地点之间可能有多条道路连通,但是并不存在一条两端都是同一个地点的道路. 不过这个鬼屋虽然很大,但是其中的道路并不算多,所以小Hi还是希望能够知道从入口到出口的最短距离是多少? 提示:Super Programming Festiv