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