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