单源最短路径

来源:互联网 发布:中职技能大赛网络搭建 编辑:程序博客网 时间:2024/06/05 00:49

1、实验环境
Visual C++ 6.0
2、实验目的和要求
目的:给定一个带权有向图G=(V,E),其中每条边的权是一个实数。另外,还给定V中的一个顶点,称为源。现在要计算从源到其他所有各顶点的最短路径长度。这里的长度就是指路上各边权之和。

3、解题思路、伪代码
3.1解题思路:将一个图G中所有的顶点V分成两个顶点集合S和T。以v为源点已经确定了最短路径的终点并入S集合中,S初始时只含顶点v,T则是尚未确定到源点v最短路径的顶点集合。然后每次从T集合中选择S集合点中到T路径最短的那个点,并加入到集合S中,并把这个点从集合T删除。直到T集合为空为止。
具体步骤
1)选一顶点v为源点,并视从源点v出发的所有边为到各顶点的最短路径(确定数据结构:因为求的是最短路径,所以①就要用一个记录从源点v到其它各顶点的路径长度数组dist[],开始时,dist是源点v到顶点i的直接边长度,即dist中记录的是邻接阵的第v行。②设一个用来记录从源点到其它顶点的路径数组path[],path中存放路径上第i个顶点的前驱顶点)。
2)在上述的最短路径dist[]中选一条最短的,并将其终点(即

#include <stdlib.h>#define M 100#define N 100#define INT_MAX 99999999#define TRUE 1#define FALSE 0typedef struct node{    int matrix[N][M];      //邻接矩阵    int n;                 //顶点数    int e;                 //边数}MGraph;void DijkstraPath(MGraph g,int *dist,int *path,int v0)   //v0表示源顶点{    int i,j,k;    int *visited=(int *)malloc(sizeof(int)*g.n);  //n个点    for(i=0;i<g.n;i++){        if(g.matrix[v0][i]!=INT_MAX&&i!=v0){            dist[i]=g.matrix[v0][i];            path[i]=v0;     //path记录最短路径上从v0到i的前一个顶点        }else{            path[i]=-1;        }         visited[i]=FALSE;  //代表还没确定    }    path[v0]=v0;    dist[v0]=0;    visited[v0]=TRUE;    for(i=1;i<g.n;i++)     //循环扩展n-1次    {        int min=INT_MAX;        int u;        for(j=0;j<g.n;j++)    //寻找未被扩展的权值最小的顶点        {            if(visited[j]==FALSE&&dist[j]<min)  //这个min是个循环,循环出最小的            {                min=dist[j];                u=j;            }        }        visited[u]=TRUE;     //顶点u加入s集        for(k=0;k<g.n;k++)   //更新dist数组的值和路径的值        {            if(visited[k]==FALSE&&min+g.matrix[u][k]<dist[k])            {                dist[k]=min+g.matrix[u][k];                path[k]=u;            }        }    }}void main(){    int n,e;     //表示输入的顶点数和边数    printf("输入顶点数和边数:");    scanf("%d %d",&n,&e);    if(e!=0){     int i,j;     int s,t,w;      //表示存在一条边s->t,权值为w     MGraph g;        int v0;        int *dist=(int *)malloc(sizeof(int)*n);        int *path=(int *)malloc(sizeof(int)*n);        for(i=0;i<n;i++)            for(j=0;j<n;j++)                g.matrix[i][j]=INT_MAX; //默认是最大值        g.n=n;        g.e=e;        printf("输入权值(先输入两点,在输入两点之间的边):");        for(i=0;i<e;i++)  //给矩阵赋值        {            scanf("%d %d %d",&s,&t,&w);            g.matrix[s][t]=w;        }        printf("输入源点:");        scanf("%d",&v0);        DijkstraPath(g,dist,path,v0);        printf("--------------------------------------\n");            /*设置输出*/        for(i=0;i<=n;i++){          if(i!=v0 && dist[i]<INT_MAX) /*源点到源点;源点到某点最长路径为无穷大的都不需要输出*/                      {printf("\n从 %d 到 %d,最短路径 %d \n%d",v0,i,dist[i],i);                j=i;                do{ j=path[j];                printf("<---%d",j);                 } while(j!=v0); /*输出直到前一个结点为源点为止,倒序输出*/                 }                 }  printf("\n");  }}

4、实验步骤
4.1输入:输入带权图:顶点,边数,图中的带权边。如图:
这里写图片描述
输出:
这里写图片描述
5、总结
单源最短路径问题采用Dijkstra算法,以最短路径长度递增,逐次生成最短路径的算法。把图中的点分成两个集合,一个是确定的最短路径的终点的集合S,一个是未确定的V-S集合,通过逐次生成最短路径,把顶点放入S集合,全部放入则结束。

0 0
原创粉丝点击