图的传递闭包
给定一个有向图,找出给定图中所有顶点对 (i, j) 的顶点 j 是否可以从另一个顶点 i 到达。这里可达意味着有一条从顶点 i 到 j 的路径。可达性矩阵称为图的传递闭包。
For example, consider below graph
Transitive closure of above graphs is
1 1 1 1
1 1 1 1
1 1 1 1
0 0 0 1
该图以邻接矩阵的形式给出,例如 'graph[V][V]' 其中如果从顶点 i 到顶点 j 有一条边,或者 i 等于 j,则 graph[i][j] 为 1,否则为图[i][j] 为 0。
可以使用 Floyd Warshall 算法,我们可以使用 Floyd Warshall 计算距离矩阵 dist[V][V],如果 dist[i][j] 是无限的,则 j 是从 I 不可到达的。否则,j 是可到达的,并且dist[i][j] 的值将小于 V。
对于这个特定问题,我们可以在空间和时间方面对其进行优化,而不是直接使用 Floyd Warshall。以下是优化:
- 我们可以创建一个布尔可达能力矩阵reach[V][V](节省空间),而不是整数结果矩阵(floyd warshall 中的 dist[V][V])。如果 j 可以从 i 到达,则值 reach[i][j] 将为 1,否则为 0。
- 我们可以使用逻辑运算,而不是使用算术运算。对于算术运算'+',使用逻辑和'&&',对于min,逻辑或'||'用来。 (我们通过一个常数因子节省时间。但时间复杂度是相同的)
下面是上述方法的实现:
C++
// Program for transitive closure
// using Floyd Warshall Algorithm
#include
// Number of vertices in the graph
#define V 4
// A function to print the solution matrix
void printSolution(int reach[][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, .. 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);
}
/* A utility function to print solution */
void printSolution(int reach[][V])
{
printf ("Following matrix is transitive");
printf("closure of the given graph\n");
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
/* because "i==j means same vertex"
and we can reach same vertex
from same vertex. So, we print 1....
and we have not considered this in
Floyd Warshall Algo. so we need to
make this true by ourself
while printing transitive closure.*/
if(i == j)
printf("1 ");
else
printf ("%d ", reach[i][j]);
}
printf("\n");
}
}
// Driver Code
int main()
{
/* Let us create the following weighted graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3 */
int graph[V][V] = { {1, 1, 0, 1},
{0, 1, 1, 0},
{0, 0, 1, 1},
{0, 0, 0, 1}
};
// Print the solution
transitiveClosure(graph);
return 0;
}
Java
// Program for transitive closure
// using Floyd Warshall Algorithm
import java.util.*;
import java.lang.*;
import java.io.*;
class GraphClosure
{
final static int V = 4; //Number of vertices in a graph
// Prints transitive closure of graph[][] using Floyd
// Warshall algorithm
void transitiveClosure(int graph[][])
{
/* reach[][] will be the output matrix that will finally
have the shortest distances between every pair of
vertices */
int reach[][] = new int[V][V];
int 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]!=0) ||
((reach[i][k]!=0) && (reach[k][j]!=0))?1:0;
}
}
}
// Print the shortest distance matrix
printSolution(reach);
}
/* A utility function to print solution */
void printSolution(int reach[][])
{
System.out.println("Following matrix is transitive closure"+
" of the given graph");
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++) {
if ( i == j)
System.out.print("1 ");
else
System.out.print(reach[i][j]+" ");
}
System.out.println();
}
}
// Driver Code
public static void main (String[] args)
{
/* Let us create the following weighted graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3 */
/* Let us create the following weighted graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3 */
int graph[][] = new int[][]{ {1, 1, 0, 1},
{0, 1, 1, 0},
{0, 0, 1, 1},
{0, 0, 0, 1}
};
// Print the solution
GraphClosure g = new GraphClosure();
g.transitiveClosure(graph);
}
}
// This code is contributed by Aakash Hasija
Python3
# Python program for transitive closure using Floyd Warshall Algorithm
#Complexity : O(V^3)
from collections import defaultdict
#Class to represent a graph
class Graph:
def __init__(self, vertices):
self.V = vertices
# A utility function to print the solution
def printSolution(self, reach):
print ("Following matrix transitive closure of the given graph ")
for i in range(self.V):
for j in range(self.V):
if (i == j):
print ("%7d\t" % (1),end=" ")
else:
print ("%7d\t" %(reach[i][j]),end=" ")
print()
# Prints transitive closure of graph[][] using Floyd Warshall algorithm
def transitiveClosure(self,graph):
'''reach[][] will be the output matrix that will finally
have reachability values.
Initialize the solution matrix same as input graph matrix'''
reach =[i[:] for i in graph]
'''Add all vertices one by one to the set of intermediate
vertices.
---> Before start of a iteration, we have reachability value
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 an iteration, vertex no. k is
added to the set of intermediate vertices and the
set becomes {0, 1, 2, .. k}'''
for k in range(self.V):
# Pick all vertices as source one by one
for i in range(self.V):
# Pick all vertices as destination for the
# above picked source
for j in range(self.V):
# 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] or (reach[i][k] and reach[k][j])
self.printSolution(reach)
g= Graph(4)
graph = [[1, 1, 0, 1],
[0, 1, 1, 0],
[0, 0, 1, 1],
[0, 0, 0, 1]]
#Print the solution
g.transitiveClosure(graph)
#This code is contributed by Neelam Yadav
C#
// C# Program for transitive closure
// using Floyd Warshall Algorithm
using System;
class GFG
{
static int V = 4; // Number of vertices in a graph
// Prints transitive closure of graph[,]
// using Floyd Warshall algorithm
void transitiveClosure(int [,]graph)
{
/* reach[,] will be the output matrix that
will finally have the shortest distances
between every pair of vertices */
int [,]reach = new int[V, V];
int 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] != 0) ||
((reach[i, k] != 0) &&
(reach[k, j] != 0)) ? 1 : 0;
}
}
}
// Print the shortest distance matrix
printSolution(reach);
}
/* A utility function to print solution */
void printSolution(int [,]reach)
{
Console.WriteLine("Following matrix is transitive" +
" closure of the given graph");
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++){
if (i == j)
Console.Write("1 ");
else
Console.Write(reach[i, j] + " ");
}
Console.WriteLine();
}
}
// Driver Code
public static void Main (String[] args)
{
/* Let us create the following weighted graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3 */
/* Let us create the following weighted graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3 */
int [,]graph = new int[,]{{1, 1, 0, 1},
{0, 1, 1, 0},
{0, 0, 1, 1},
{0, 0, 0, 1}};
// Print the solution
GFG g = new GFG();
g.transitiveClosure(graph);
}
}
// This code is contributed by 29AjayKumar
Javascript
输出
Following matrix is transitiveclosure of the given graph
1 1 1 1
0 1 1 1
0 0 1 1
0 0 0 1