# Final 2021.08.11
* Enunciado: https://www.cubawiki.com.ar/images/4/4b/Final_del_11-08-21_(Algoritmos_III).pdf
###### tags: `Finales`
## Resumen
### Glosario/definiciones
* TSP: https://en.wikipedia.org/wiki/Travelling_salesman_problem NPC
### Trucos
* Para demostrar/refutar las implicaciones, intentar el contrarrecíproco: $p => q <=> ¬q => ¬p$
### Errores comunes
* No saber la complejidad de problemas conocidos (por ejemplo, TSP)
## Resolución
### 1: Sea $M ∈ N^{m×n}$ una matriz de números naturales. Se desea obtener un camino que empiece en la casilla superior izquierda ($[1, 1]$), termine en la casilla inferior derecha ($[m, n]$), y tal que minimice la suma de los valores de las casillas por las que pasa. En cada casilla $[i, j]$ hay dos movimientos posibles: ir hacia abajo (a la casilla $[i + 1, j]$), o ir hacia la derecha (a la casilla $[i, j + 1]$).
#### a) Función
$F(i, j) =$
\begin{cases}
M_{m,n} & \text{si $(i,j) = (m, n)$} \\
M_{i, j} + min(F(i, j+1), F(i+1, j))& \text{si $i < m ∧ j < n$} \\
M_{i, j} + F(i+1, j)& \text{si $i < m ∧ j = n$} \\
M_{i, j} + F(i, j+1)& \text{si $i = m ∧ j < n$}
\end{cases}
Empezamos desde F(0,0), la primer posición del tablero.
En el caso general, sumamos el valor de la posición actual y tomamos el mínimo entre los dos subcaminos posibles: si bajamos o si vamos a la derecha.
Cuando estamos en los bordes, hay solo una dirección posible por la que podemos continuar, por lo que el llamado recursivo en este caso es uno solo.
Terminamos al llegar a la posición objetivo (m, n), devolviendo el valor de esta posición (caso base).
#### b) Algoritmo
```python
Memo = [M][N]
def f(i, j):
if Memo[i][j] != UNDEFINED
return Memo[i][j]
if (i, j) == (m, n):
Memo[i][j] = M[m][n]
if i < m and j < n:
Memo[i][j] = M[i][j] + min(f(i, j+1), f(i+1, j))
if i < m and j == n:
Memo[i][j] = M[i][j] + f(i+1, j)
if i == m and j < n:
Memo[i][j] = M[i][j] + f(i, j+1)
return Memo[i][j]
def reconstruir_camino():
i, j = 0, 0
camino = [(i, j)]
while ((i, j) != (m, n)):
valor_derecha = inf if (j+1 == n) else Memo[i][j+1]
valor_abajo = inf if (i+1 == m) else Memo[i+1][j]
if (valor_derecha < valor_abajo):
j = j+1
else:
i = i+1
camino.append((i, j))
return camino
f(0, 0)
return reconstruir_camino()
```
#### c) Complejidad
$O(mn)$ estados posibles
cada uno calculado en $O(1)$
$\text{reconstruir_camino}$ cuesta $O(m+n)$
costo total: $O(m.n)+O(m+n) = O(m.n)$
### 2: Sea $G$ un grafo conexo con pesos asociados a sus aristas. Sean $v$ y $w$ dos vértices distintos de $G$. Decimos que un camino entre $v$ y $w$ es min-max si minimiza el peso de la arista mas pesada del camino (sobre el conjunto de todos los caminos entre v y w que haya en G). Sea $T$ un árbol generador mínimo de $G$, y sea $P$ el unico camino entre $v$ y $w$ que hay en $T$. Demostrar que $P$ es un camino min-max entre $v$ y $w$. Es decir, demostrar que para todo camino $P′$ entre $v$ y $w$ que haya en $G$, el peso de la arista más pesada de $P$ es menor o igual que el peso de la arista mas pesada de $P′$.
#### Telegram
> Sean u, v arbitrarios. Tomá un camino entre u y v en T. Sacale su arista mas pesada e. Ahora tenés dos componentes conexas, A y B. Agarra en G cualquier camino minimax P entre u y v, y asumi que su arista mas pesada es menos pesada que e. Hay una arista e' de P que cruza de A a B. Agrega e', conectando A y B. Esto te da un AGM de menor peso. Absurdo. Luego no existe tal camino P con tal arista e'.
> e es la arista de mayor peso en el único camino en T entre u y v. Llamá si querés Q a ese camino. Si llamamos w(P) al mayor peso entre todas las aristas de P, w(P) >= w(e') porque e' es una arista en P, y como asumimos que w(e) > w(P), sabemos w(e) > w(e'), y al usar e' para conectar A y B, que eran las componentes conexas en las que partimos a T cuando le sacamos e, nos queda un AGM con peso w(T) - w(e) + w(e') < w(T), lo cual no puede pasar. Luego lo que asumimos, w(e) > w(P), es falso. Luego para todo camino P entre u y v en G, w(P) >= w(e) = w(Q), que es lo que queríamos demostrar. Estaba en el celu, disculpá los typos.
> [name=Lebron] [time=Sun, Feb 18, 2022 11:36 PM] [Fuente](https://t.me/c/1461330951/4180)
### 3: Dada una red N = (V, E), con funcion de capacidad c: E → Z≥0, fuente s y sumidero t. Decidir si cada una de las siguientes afirmaciones es Verdadera o Falsa. Justificar.
Recordar que un arco e est ́a saturado por el flujo f si f (e) = c(e).
a) Para cualquier flujo m ́aximo entero f y arco e no saturado por f , si se incrementa c(e) en
uno, el valor del flujo m ́aximo de N se incrementa.
b) Para cualquier flujo m ́aximo entero f y arco e no saturado por f , si se incrementa c(e) en
uno, el valor del flujo m ́aximo de N nunca se incrementa.
c) Para cualquier flujo m ́aximo entero f y arco e saturado por f , si se incrementa c(e) en uno,
el valor del flujo m ́aximo de N se incrementa.
d) Para cualquier camino P desde s a t en N , si la capacidad de cada arco en P se incrementa
en uno, entonces el valor de flujo m ́aximo de N aumenta.
e) Para cualquier camino P desde s a t en N , si la capacidad de cada arco en P se incrementa
en uno, entonces el valor de flujo m ́aximo de N aumenta como m ́aximo en uno.
### 4: Justificar todas las respuestas.
#### (a) Dado un problema de decisión $Π$, si mostramos una reduccion polinomial de $Π$ a $TSP$ y otra de $TSP$ a $Π$, decidir si cada una de las siguientes sentencias se desprenden de estos hechos:
##### i. $Π$ es NP-difícil pero no NP-completo.
Falso.
Como podemos reducir $Π$ a TSP, sabemos que TSP es igual o más difícil que $Π$. Y como también sabemos que TSP se puede reducir a $Π$, entonces $Π$ es igual o más difícil que TSP. Por ende, $Π$ tiene que ser igual de difícil que TSP, el cual sabemos que pertenece a NPC
##### ii. $Π$ es NP pero no NP-completo.
Falso: es NP (certificado trivial usando la transformación y que TSP es NP) y también NPC (porque es NP-hard por poder reducirse TSP a él y TSP ser NPC).
##### iii. $Π$ es NP-completo.
Verdadero: TSP es NP-completo. Al poder reducirse el uno al otro, sabemos que son igual de difíciles.
##### iv. $Π$ no es NP-difícil ni NP-completo.
Falso: Ver punto anterior (NPC implica NP-difícil).
##### v. $Π$ esta en P.
Falso: P no está en NPC.
#### (b) Decidir si cada una de las siguientes sentencias es verdadera o falsa:
##### i. Un problema $Π ∈ NP$ es NP-completo si puede ser reducido a $SAT$ en tiempo polinomial.
Falso.
Para ser NPC, tiene que ser NP y NP-hard. Que $Π$ pueda ser reducido a SAT no implica que $Π$ pertenezca a NP-hard.
Si la reducción fuera al revés, de SAT a $Π$, podríamos afirmar que pertenece a NPC por el teorema de Cook-Levin.
##### ii. Un problema $Π ∈ NP$ es NP-completo si $SAT$ puede ser reducido a ́el en tiempo polinomial.
Verdadero: Ver inciso anterior.
##### iii. Si $NP = coNP$ entonces $P = NP$.
Falso: que todo problema cuyas instancias positivas puedan ser certificadas polinomialmente, cumpla que sus instancias negativas también puedan serlo y viceversa, no implica que existan algoritmos polinomiales para resolverlos.
##### iv. Si $NP ≠ coNP$ entonces $P ≠ NP$.
Afirmación equivalente a su contrarrecíproca: $P = NP => NP = coNP$
Verdadero: Si $P = NP$, significa que para todo problema $NP$ existe un algoritmo polinomial que lo resuelve. De esta forma, podemos certificar instancias (tanto negativas como positivas) en tiempo polinomial usando el certificado trivial (la instancia) y el algoritmo polinomial que lo resuelve como verificador.