我发现了以下内容:
给定有向图,找出给定图中所有顶点对(i,j)的顶点j是否可以从另一个顶点i到达。
此处可达表示存在从顶点i到j的路径。
达到能力矩阵称为图的传递闭包。
图形以邻接矩阵的形式给出'graph [V] [V]',其中如果从顶点i到顶点j或i等于j,则graph [i] [j]为1 ,否则graph [i] [j]为0。
我们可以使用Floyd Warshall计算距离矩阵dist [V] [V],如果dist [i] [j]是无穷大,则j不能从i到达,否则j是可达的并且dist [i]的值[j]将小于V.
// Prints transitive closure of graph[][] using Floyd Warshall algorithm
void transitiveClosure(int graph[][V])
{
/* reach[][] will be the output matrix that will finally have the shortest
distances between every pair of vertices */
int reach[V][V], i, j, k;
/* Initialize the solution matrix same as input graph matrix. Or
we can say the initial values of shortest distances are based
on shortest paths considering no intermediate vertex. */
for (i = 0; i < V; i++)
for (j = 0; j < V; j++)
reach[i][j] = graph[i][j];
/* Add all vertices one by one to the set of intermediate vertices.
---> Before start of a iteration, we have reachability values for all
pairs of vertices such that the reachability values consider only the
vertices in set {0, 1, 2, .. k-1} as intermediate vertices.
----> After the end of a iteration, vertex no. k is added to the set of
intermediate vertices and the set becomes {0, 1, 2, .. k} */
for (k = 0; k < V; k++)
{
// Pick all vertices as source one by one
for (i = 0; i < V; i++)
{
// Pick all vertices as destination for the
// above picked source
for (j = 0; j < V; j++)
{
// If vertex k is on a path from i to j,
// then make sure that the value of reach[i][j] is 1
reach[i][j] = reach[i][j] || (reach[i][k] && reach[k][j]);
}
}
}
// Print the shortest distance matrix
printSolution(reach);
}
首先,你能解释一下为什么函数的参数是graph [] [V]而不是例如图[V] [V]?
那么我们为什么要初始化矩阵,最终在每对顶点之间有最短的距离,用图[V] [V]?
你能解释一下初始化后在for循环中做了什么吗?
我们怎么能写这个命令:reach[i][j] = reach[i][j] || (reach[i][k] && reach[k][j]);
elsewhise?
编辑:图形是否为布尔矩阵?
如果是这样,那么它是否也不会到达布尔矩阵?
所以如果我们有这个命令:(达到[i] [j] =到达[i] [j] ||(到达[i] [k]&amp;&amp;到达[k] [j]);)如果达到[i] [j] = 1那么我们执行这个:达到[i] [j] =到达[i] [j],否则我们检查是否(达到[i] [k] +达到[k] [j])非零?
或者我明白错了吗?
答案 0 :(得分:0)
首先,你能解释一下为什么函数的论证是 graph [] [V]而不是例如图[V] [V]?
也可以是图[V] [V]。我更喜欢图[V] [V],因为这是预期的输入。
那么我们为什么要初始化矩阵,最终会有 每对顶点之间的最短距离,图[V] [V]?
这是因为节点a和b之间的距离肯定最多是a和b之间边缘的值(假设没有边缘则为无穷大)。 E. g。:如果我们有A和B之间有长度为5的边的图,我们肯定知道A和B之间存在长度为5的路径,但是可能存在较短的路径。
这里有一些重要的事项需要注意。如果您只对可达性感兴趣,那么您并不关心实际距离。在这种情况下,如果不存在任何路径,您可以将值设置为0,如果存在路径,则可以设置为1.
你能解释一下在初始化之后做了什么吗? for循环?
您基本上使用的是动态编程方法。解释很长,请在此处阅读:http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
我们怎么写这个命令:达到[i] [j] =到达[i] [j] || (达到[i] [k]&amp;&amp;到达[k] [j]); elsewhise?
我们可以把它写成:reach [i] [j] | =(到达[i] [k]&amp;&amp;到达[k] [j])
答案 1 :(得分:-1)
首先,你能解释一下为什么函数的参数是graph [] [V]而不是例如图[V] [V]?
该函数以这种方式声明,因此它可以接受一个轴的大小未知的二维数组。由于邻接矩阵的定义是方形的,后面定义了reach[V][V]
,我不知道他们为什么会这样定义函数。有关详细信息,请参阅this SO问题。
那么我们为什么要初始化矩阵,最终在每对顶点之间有最短的距离,用图[V] [V]?
graph
通过遍历单个边而没有中间点头来定义可以到达每个其他顶点的每个顶点。当我们开始算法时,这些是最短的路径,只有我们知道从一个顶点到另一个顶点的路径。通常,如果顶点通过直接路径彼此无法访问,graph
会将该边缘定义为零(无连接)或无限(它们之间的距离太大而无法通行)。
你能解释一下初始化后在for循环中做了什么吗?
首先,了解这一行:
reach[i][j] = reach[i][j] || (reach[i][k] && reach[k][j]);
它问:“顶点是否可以从顶点j到达?或者可以通过中间顶点k从顶点j到达顶点吗?”
这解释了为什么你需要三个for循环。他们为什么这样订购呢?
想象一下,你有如上所述的相同行,并且如此订购for循环:
for i
for j
for k
如果是这种情况,对于每对顶点(i,j),您将检查两者是否可以通过某个中间顶点k连接。然后你就放弃了。
但是如果你必须通过两个中间顶点来获取(i,j)。 for循环的上述排序可能无法发现这种可能性。
相反,我们在外部上订购带有k的for循环,因此,找到 all k为中间点的点对。然后,我们为每个可能的中间点k执行此操作。有一些严格的方法可以证明这样做可以让你考虑两点之间的所有路径,但是,如果你考虑一下,我认为你会发现它直觉上是正确的。
我们怎么写这个命令:达到[i] [j] =到达[i] [j] || (达到[i] [k]&amp;&amp;到达[k] [j]); elsewise?
正如另一位评论员所说,你可以写:
reach[i][j] |= (reach[i][k] && reach[k][j])
你也可以写:
reach[i][j] = min(reach[i][j], reach[i][k]+reach[k][j])
如果输入图形使用无穷大来表示非连接顶点,会找到两个顶点之间最短路径的长度。
请注意:
reach[i][j] = max(reach[i][j], reach[i][k]+reach[k][j])
将是非常糟糕的主意。在一般图表中查找longest path是NP-hard:我们知道没有好办法和there probably isn't one。但是,如果你找到一个,你不仅会变得富有:整个世界将在一夜之间改变,你将永远被铭记。