This problem is solved by multiplying the matrix.
Create an n x n matrix containing 0s and 1s (1 for the cell mat[i][j] if there is a path from i to j ). Multiply this matrix by yourself k times (consider the possibility of a quick exponent of the matrix). Then in the matrix cell mat[i][j] you have the number of paths with length k , starting from i and ending with j .
NOTE Quick exponentiation of a fast matrix is basically the same as quick exponentiation, just instead you multiply numbers by matrix multiplication.
NOTE2: Assume that n is the number of vertices in the graph. Then the algorithm proposed here is executed in the time complexity O (log k * n 3 ) and has the memory complexity O (n 2 ). You can improve it a bit more if you use optimized matrix multiplication, as described here . Then O (log k * n log 2 7 ) becomes the time complexity.
EDIT According to Antoine’s request, I’ll explain the explanation of why this algorithm really works:
I will prove the algorithm by induction. The basis of induction is obvious: initially in my matrix there are a number of paths of length 1.
Suppose that to level k , if I raise the matrix to degree k , I have in mat[i][j] number of paths with length k between i and j .
Now consider the next step k + 1 . Obviously, each path of length k + 1 consists of a prefix of length k and one more edge. This basically means that paths of length k + 1 can be calculated (here I denote by mat_pow_k matrix raised to the k degree)
num_paths (x, y, k + 1) = sum i = 0 i <n mat_pow_k [x] [i] * mat [i] [y]
Again: n is the number of vertices in the graph. This may take some time to understand, but basically the original matrix has 1 in its cell mat[i][y] only if there is a direct border between x and y . And we count all the possible prefixes of such an edge to form a path of length k + 1 .
However, the last thing I wrote actually calculates the k + 1 st power of mat , which proves the step of induction and my statement.
Boris Strandjev
source share