图-最短路径-Floyd算法

给定高铁的规划方案,如何求任意两点的最短路呢?

方法是Floyd算法。

输入:创建图。

输出:任意两个顶点的最短路径以及长度。

运行结果:

算法思想:

1、计算从i出发,跳点为空,直接到j 的最短路。记做D[i][j]。

2、可选跳点为1时,i到j的路径分为两种情况:

或者不经过1, 此时前者最短为D[i][j],

或者经过1,此时最短为D[i][1]+D[1][j]

所以D[i][j]=min{D[i][j,D[i][1] + D[1][j] }

3、可选跳点为{1,2}时i到j的路径分为两种情况。

或者不经过2,此时最短为D[i][j],

或者经过2,此时最短为D[i][2] + D[i][j]

所以所以D[i][j]=min{D[i][j,D[i][2] + D[2][j] }

递推到可选跳点为{1..k}

D[i][j]=min{D[i][k],D[i][k] + D[k][j] }

可选跳点为{1..n}时,意味者对中间经过的顶点不加任何限制,此时所得的最短路就是全局最短路。D[i][j]=min{D[i][j],D[i][n] + D[n][j] }

算法复杂度O(G.vernum^3)

算法实现:

typedef char   PathMatrix[50];
typedef int    DistancMatrix[MVNUM][MVNUM];
void ShortestPath_FLOYD(MGraph G,PathMatrix P[MVNUM][MVNUM],DistancMatrix &D){
    /*用Floyd算法求有向网G中各顶点v和w之间的最短路径P[v][w]及其带权长度D[v][w]。
    计算得到跳点为空时的最短路D[i][j] 可选跳点为k时 或者不经过k 此时前者最短D
    [i][j] 经过1此时最短为D[i][1]+D[1][k] 可选跳点到n时 意味着对中间的顶点没
    有限制 ,此时的最短路就是全局最短路  */
    int i,j,k;
    char s[5],s1[50],s2[50];
    for(i=0;i<G.vexnum;i++)
        for(j=0;j<G.vexnum;j++)	{
	    D[i][j]=G.arcs[i][j].adj;
	    if(D[i][j]<INFINITY){
	         s[0]=G.vexs[i];
		 s[1]='-';
	         s[2]='>';
	         s[3]=G.vexs[j];
		 s[4]='\0';
		 strcpy(P[i][j],s);
	    }
        }
    for(k=0;k<G.vexnum;k++)
        for(i=0;i<G.vexnum;i++)
	    for(j=0;j<G.vexnum;j++)
	        if(D[i][j]>D[i][k]+D[k][j]) {           //如果只关心两点间是否有通路,则可以用1和0表示连通与不连通
	            D[i][j]=D[i][k]+D[k][j];            //改为:d[i][j] = d[i][j]||(d[i][k] && d[k][j]) 是为有向图的传递闭包
		    strcpy(s1,P[i][k]);
                    strcpy(s2,P[k][j]);
		    strcpy(P[i][j],strcat(s1,Change(s2)));
		}
     for(i=0;i<G.vexnum;i++)
         for(j=0;j<G.vexnum;j++)
	     if(i!=j)
		printf("%s %d\n",P[i][j],D[i][j]);
}

修改字符串 删去s串第一个字母.

char *Change(char *s){
	//修改字符串 删去s串第一个字母
   int l=strlen(s);
   for(int i=0;i<l;i++)
      s[i]=s[i+1];
   return s;
}

邻接表存储:

void ShortestPath_FLOYD(ALGraph G,PathMatrix P[MVNUM][MVNUM],DistancMatrix &D){
    /*用Floyd算法求有向网G中各顶点v和w之间的最短路径P[v][w]及其带权长度D[v][w]。
    计算得到跳点为空时的最短路D[i][j] 可选跳点为k时 或者不经过k 此时前者最短D
    [i][j] 经过1此时最短为D[i][k]+D[1][k] 可选跳点到n时 意味着对中间的顶点没
    有限制 ,此时的最短路就是全局最短路 */
    int i,j,k;
    char s[5],s1[50],s2[50];
    ArcNode *p;
    for(i=0;i<G.vexnum;i++)
	for(j=0;j<G.vexnum;j++)
	    D[i][j]=INFINITY;
    for(i=0;i<G.vexnum;i++)
        for(p=G.vertices[i].firstarc;p!=NULL;p=p->nextarc) {
	     k=p->adjvex;
	     D[i][k]=p->adj;
             s[0]=G.vertices[i].data;
	     s[1]='-';
             s[2]='>';
             s[3]=G.vertices[k].data;
	     s[4]='\0';
	     strcpy(P[i][k],s);
	 }
    for(k=0;k<G.vexnum;k++)
        for(i=0;i<G.vexnum;i++)
	    for(j=0;j<G.vexnum;j++){
                if(D[i][j]>D[i][k]+D[k][j]){
		    D[i][j]=D[i][k]+D[k][j];
		    strcpy(s1,P[i][k]);
                    strcpy(s2,P[k][j]);
		    strcpy(P[i][j],strcat(s1,Change(s2)));
		}
	    }

    for(i=0;i<G.vexnum;i++)
        for(j=0;j<G.vexnum;j++)
	    if(i!=j)
		printf("%s %d\n",P[i][j],D[i][j]);
}

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值