实用算法实现-第 21 篇 每对顶点间的最短路径

21.1 每对顶点间最短路径与矩阵乘法

考虑矩阵乘法D*D,有:

d’’(i, j) = ∑(d’ (i, k) * d’ (k, j))

考虑有向图每对顶点间的距离邻接矩阵。w(i, j)为由i点都j点的路径距离。故此有矩阵W的i行向量为i到点集合{j, 1≤j≤n}的距离。而矩阵W的j列向量为点集合{i, 1≤i≤n}到j的距离。

要求最短路径,可以先考虑某一个点i到j的较短路径的求法。由i点到j点,可以通过点集合{k, 1≤k≤n}中任意一点作为中间结点。i通过这些中间点到达j的最短路径就是一条较短的路径。故此i到j的较短路径长度为:

W’’(i, j) = min(w’ (i, k) + w’ (k, j))

可以发现上述两式子的相似之处,将‘+’看做‘*’,将‘min’看做‘∑’。可以将求每对顶点间的最短路径问题转化为矩阵乘法。

由于这里i到j的这条较短路径只是经过一个中间结点的最短路径,所以不一定是图的最短路径。可以知道i到j的最短路径最多需要进过n-1个中间结点,所以需要重复上述运算log(n-1)次即可。

朴素的矩阵乘法可以在O(n^3)时间内完成,故此该算法的复杂度为O(n^3*log(n))。虽然这种算法较之Floyd-Wallshall算法的O(n^3)要差,但是这种算法可能在并行计算机中能被很好地优化,因为矩阵乘法在并行计算机中有很多优化办法。

21.2 Floyd-Warshall算法

21.2.1实例

PKU JudgeOnline, 3660, Cow Contest.

21.2.2问题描述

给出n只奶牛,如果奶牛a的技能值比奶牛b大,那么a就能打败b,现在给出n只奶牛中m对奶牛的技能。对比情况,输出能确定多少只奶牛的排名。

21.2.3输入

55

43

42

32

12

2 5

21.2.4输出

2

21.2.5分析

某只奶牛能否确定其排名,只要能被它打败的奶牛数加上能打败它的奶牛数等于n-1就可用图的语言描述就是顶点的出度加上这个顶点的入度等于n-1(如果顶点i和顶点j能过通过顶点k相连,那么就把顶点k和顶点i相连)。

21.2.6程序

#include <stdio.h> #include <string.h> int main() { boolhash[101][101],map[101][101]; int n,m; int i,j,k; scanf("%d%d",&n,&m); memset(hash,false,sizeof(hash)); memset(map,false,sizeof(map)); for(i=0;i<m;i++) { inta,b; scanf("%d%d",&a,&b); hash[a][b]=true; map[b][a]=true; } for(k=1;k<=n;k++){ for(i=1;i<=n;i++){ for(j=1;j<=n;j++) { hash[i][j]=hash[i][j]||hash[i][k]&&hash[k][j]; map[i][j]=map[i][j]||map[i][k]&&map[k][j]; } } } intmax,min; int c=0; for(i=1;i<=n;i++) { max=min=0; for(j=1;j<=n;j++) { if(i==j) continue; if(map[i][j]) min++; if(hash[i][j]) max++; } if(max+min==n-1) c++; } printf("%d\n",c); return 0; }
21.3 实例

PKU JudgeOnline, 3660, Cow Contest.

本文章欢迎转载,请保留原始博客链接http://blog.csdn.net/fsdev/article

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值