图的最短路径:Dijkstra 和 Floyd

//最短路径
/*



dijkstra
Dijkstra(迪杰斯特拉)算法的核心思想是贪心策略+动态规划 http://www.programgo.com/article/4721147659/
Dijkstra算法能得出最短路径的最优解,但是效率低 */
 

Floyed 算法:

  Floyed算法比较简单,其思想可以参照三角形的特性中,两边和与第三边的关系,a 和 b的最短路径要么是(a,b)要么是(a,c,b),这取决于 a->b和a->c->b的大小。

算法思想原理:

     Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)

      从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

 

 

/* 用邻接矩阵表示的图的Dijkstra算法的源程序*/

#include <iostream>
using namespace std;
#define MAXVEX 100
#define MAX 1e+8
typedef char VexType;
typedef float AdjType;

typedef struct
{
    int n;                            //图的顶点个数
  //  VexType vexs[MAXVEX];            //顶点
    AdjType arcs[MAXVEX][MAXVEX];   //
}GraphMatrix;

typedef struct {
  //  VexType vertex;           //顶点信息
    AdjType length;       // 最短路径长度
    int prevex;          // 从v0到达vi(i=1,2,…n-1)的最短路径上vi的前驱顶点
}Path;
Path dist[6];          // n为图中顶点个数

void dijkstra(GraphMatrix graph, Path dist[])
{
    int i,j,minvex;
    AdjType min; // 初始化,此时集合U中只有顶点v0
    dist[0].length = 0;    dist[0].prevex = 0;   
    graph.arcs[0][0] = 1;   // 表示顶点v0在集合U中

    for(i = 1; i < graph.n; i++) 
    {  // 初始化集合V-U中顶点的距离值
        dist[i].length=graph.arcs[0][i];
        if (dist[i].length != MAX)
            dist[i].prevex=0;
        else  dist[i].prevex= -1;
    }
    for(i = 1; i < graph.n; i++) 
    {
        min=MAX;    minvex=0;
        for (j = 1; j < graph.n; j++) //在V-U中选出距离值最小顶点
            if( graph.arcs[j][j] == 0 && dist[j].length < min ) 
            {
                min=dist[j].length;  minvex=j;
            }
        if(minvex == 0) break;    // 从v0没有路径可以通往集合V-U中的顶点
        graph.arcs[minvex][minvex] = 1;    // 集合V-U中路径最小的顶点为minvex
        for (j = 1; j < graph.n; j++) 
        {    
            // 调整集合V-U中的顶点的最短路径
            if(graph.arcs[j][j] == 1)  continue;
            if(dist[j].length > dist[minvex].length + graph.arcs[minvex][j]) {
                dist[j].length = dist[minvex].length + graph.arcs[minvex][j];
                dist[j].prevex = minvex;
            }
        }
    }
}

GraphMatrix graph;

void initgraph(){
    int i,j;
    graph.n=6;
    for (i = 0; i < graph.n; i++)
        for (j = 0; j < graph.n; j++)
            graph.arcs[i][j] = (i == j ? 0 : MAX);
    graph.arcs[0][1] = 50;
    graph.arcs[0][2] = 10;
    graph.arcs[1][2] = 15;
    graph.arcs[1][4] = 5;
    graph.arcs[2][0] = 20;
    graph.arcs[2][3] = 15;
    graph.arcs[3][1] = 20;
    graph.arcs[3][4] = 35;
    graph.arcs[4][3] = 30;
    graph.arcs[5][3] = 3;
    graph.arcs[0][4] = 45;
}

int main(){
    int i;
    initgraph();
    dijkstra(graph, dist);
    for (i = 0; i < graph.n; i++)
        printf("(%.0f %d)\t", dist[i].length,dist[i].prevex);
    system("pause");
    return 0;
}

 

 

 

//============================================================================
//Floyed: 往点中间插入其他点,动态:s[i][k] + s[k][j] < s[i][j]
//test case
/
//============================================================================


#include <iostream>
using namespace std;
int main()
{
    int n,m,i,j,k,l,r;
    cout<<"输入结点数和边数\n";
    cin>>n>>m;

    int**s=new int*[n];//确定的是行数
    for(int i=0;i<n;i++)
    {
        s[i]=new int[n];//确定的是列数
    }
    //初始化,将自己与自己的距离置为0,任意两点距离置为99999
    for(i=0;i<n;i++){
        for(j=0;j<n;j++)
        {  if(i==j)  s[i][j]=0;
        s[i][j]=99999;
        }
    }

    //Input:
    cout<<"输入结点和两个结点的权值\n";
    for(k=0;k<m;k++)
    {
        cin>>i>>j;
        cin>>s[i][j];
    }

    for (k=0; k<n; k++)
        for (i=0; i<n; i++)
            for (j=0; j<n; j++)
                if (s[i][k] + s[k][j] < s[i][j])
                    s[i][j] = s[i][k] + s[k][j];
    cout<<"输入起始和终止结点"<<endl;
    cin>>l>>r;
    cout<<s[l][r]<<endl;
    system("pause");
    return 0;
}
*
10 16
0 1
4
0 2
1
1 4
9
1 5
8
2 4
6
2 3
1
2 6
8
3 5
4
3 6
7
6 8
5
4 7
5
4 8
6
5 7
8
5 8
6
7 9
7
8 9
3
*/

 

转载于:https://www.cnblogs.com/tianjintou/p/4527676.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值