Skip to Content

Número de caminos de longitud fija / Caminos más cortos de longitud fija

El siguiente artículo describe soluciones a estos dos problemas construidas sobre la misma idea: reducir el problema a la construcción de una matriz y calcular la solución con la multiplicación de matrices usual o con una multiplicación modificada.

Número de caminos de una longitud fija

Nos dan un grafo dirigido, no ponderado GG con nn vértices y nos dan un entero kk. La tarea es la siguiente: para cada par de vértices (i,j)(i, j) hay que encontrar el número de caminos de longitud kk entre estos vértices. Los caminos no tienen que ser simples, es decir, los vértices y las aristas se pueden visitar cualquier número de veces en un solo camino.

Asumimos que el grafo se especifica con una matriz de adyacencia, es decir, la matriz G[][]G[][] de tamaño n×nn \times n, donde cada elemento G[i][j]G[i][j] es igual a 11 si el vértice ii está conectado con jj por una arista, y 00 si no están conectados por una arista. El siguiente algoritmo también funciona en el caso de aristas múltiples: si algún par de vértices (i,j)(i, j) está conectado con mm aristas, entonces podemos registrar esto en la matriz de adyacencia poniendo G[i][j]=mG[i][j] = m. También el algoritmo funciona si el grafo contiene bucles (un bucle es una arista que conecta un vértice consigo mismo).

Es obvio que la matriz de adyacencia construida es la respuesta al problema para el caso k=1k = 1. Contiene el número de caminos de longitud 11 entre cada par de vértices.

Construiremos la solución de forma iterativa: Supongamos que conocemos la respuesta para algún kk. Aquí describimos un método para construir la respuesta para k+1k + 1. Denotemos por CkC_k la matriz para el caso kk, y por Ck+1C_{k+1} la matriz que queremos construir. Con la siguiente fórmula podemos calcular cada entrada de Ck+1C_{k+1}:

Ck+1[i][j]=p=1nCk[i][p]G[p][j]C_{k+1}[i][j] = \sum_{p = 1}^{n} C_k[i][p] \cdot G[p][j]

Es fácil ver que la fórmula no calcula otra cosa que el producto de las matrices CkC_k y GG:

Ck+1=CkGC_{k+1} = C_k \cdot G

Así, la solución del problema se puede representar de la siguiente forma:

Ck=GGGk times=GkC_k = \underbrace{G \cdot G \cdots G}_{k \text{ times}} = G^k

Resta notar que los productos de matrices se pueden elevar a una potencia alta de forma eficiente usando exponenciación binaria. Esto da una solución con complejidad O(n3logk)O(n^3 \log k).

Caminos más cortos de una longitud fija

Nos dan un grafo dirigido ponderado GG con nn vértices y un entero kk. Para cada par de vértices (i,j)(i, j) hay que encontrar la longitud del camino más corto entre ii y jj que consiste de exactamente kk aristas.

Asumimos que el grafo se especifica por una matriz de adyacencia, es decir, vía la matriz G[][]G[][] de tamaño n×nn \times n donde cada elemento G[i][j]G[i][j] contiene la longitud de las aristas del vértice ii al vértice jj. Si no hay arista entre dos vértices, entonces el elemento correspondiente de la matriz se asignará a infinito \infty.

Es obvio que en esta forma la matriz de adyacencia es la respuesta al problema para k=1k = 1. Contiene las longitudes de los caminos más cortos entre cada par de vértices, o \infty si no existe un camino que consista de una arista.

Otra vez podemos construir la solución al problema de forma iterativa: Supongamos que conocemos la respuesta para algún kk. Mostramos cómo podemos calcular la respuesta para k+1k+1. Denotemos LkL_k la matriz para kk y Lk+1L_{k+1} la matriz que queremos construir. Entonces la siguiente fórmula calcula cada entrada de Lk+1L_{k+1}:

Lk+1[i][j]=minp=1n(Lk[i][p]+G[p][j])L_{k+1}[i][j] = \min_{p = 1 \ldots n} \left(L_k[i][p] + G[p][j]\right)

Al mirar más de cerca esta fórmula, podemos trazar una analogía con la multiplicación de matrices: de hecho la matriz LkL_k se multiplica por la matriz GG, la única diferencia es que en lugar de la operación de multiplicación tomamos el mínimo en lugar de la suma, y la suma en lugar de la multiplicación como operación interna.

Lk+1=LkG,L_{k+1} = L_k \odot G,

donde la operación \odot se define de la siguiente forma:

AB=C    Cij=minp=1n(Aip+Bpj)A \odot B = C~~\Longleftrightarrow~~C_{i j} = \min_{p = 1 \ldots n}\left(A_{i p} + B_{p j}\right)

Así, la solución de la tarea se puede representar usando la multiplicación modificada:

Lk=GGk times=GkL_k = \underbrace{G \odot \ldots \odot G}_{k~\text{times}} = G^{\odot k}

Resta notar que también podemos calcular esta exponenciación de forma eficiente con exponenciación binaria, porque la multiplicación modificada es obviamente asociativa. Así que también esta solución tiene complejidad O(n3logk)O(n^3 \log k).

Generalización de los problemas para caminos con longitud hasta kk {data-toc-label=“Generalización de los problemas para caminos con longitud hasta k”}

Las soluciones de arriba resuelven los problemas para un kk fijo. Sin embargo las soluciones se pueden adaptar para resolver problemas en los que se permite que los caminos contengan no más de kk aristas.

Esto se puede hacer modificando ligeramente el grafo de entrada.

Duplicamos cada vértice: para cada vértice vv creamos un vértice más vv’ y agregamos la arista (v,v)(v, v’) y el bucle (v,v)(v’, v’). El número de caminos entre ii y jj con a lo sumo kk aristas es el mismo número que el número de caminos entre ii y jj’ con exactamente k+1k + 1 aristas, ya que hay una biyección que mapea cada camino [p0=i, p1, , pm1, pm=j][p_0 = i,p_1,\ldots,~p_{m-1},~p_m = j] de longitud mkm \le k al camino [p0=i, p1, , pm1, pm=j,j,,j][p_0 = i,p_1,\ldots,~p_{m-1},~p_m = j, j’, \ldots, j’] de longitud k+1k + 1.

El mismo truco se puede aplicar para calcular los caminos más cortos con a lo sumo kk aristas. Otra vez duplicamos cada vértice y agregamos las dos aristas mencionadas con peso 00.