La solución
La pieza que faltaba en el rompecabezas
La propiedad de los grafos arbóreos que no conocía ni intuía y que necesitaba conocer para poder encontrar el $O(n \log n)$ es que para cada árbol de $n$ puede elegir una raíz tal que ningún subárbol tenga más de $n/2$ nodos, o, como dijo @Dap, cada gráfico de árbol $G$ tiene al menos $1$ vértice $r$ de manera que los componentes de $G-r$ todos tienen un orden como máximo $n/2$ o todo árbol tiene un centro . Una vez que sabes eso, todo lo demás encaja.
Introducción
Las respuestas de Dap y SmileyCraft contenían elementos útiles, pero eran demasiado complicadas y no pude demostrar que su complejidad en el peor de los casos fuera mejor que $O(n^2)$ aunque probablemente sean mejores que eso. Mi solución es bastante parecida a la de Dap, pero más sencilla. Para mí, sin embargo, era la simplificación que me interesaba más que la solución real.
Como los grafos arbóreos son tan especiales, se habla de ellos en la teoría de grafos, en la teoría de conjuntos y en la informática, a veces con nombres y símbolos diferentes, como habrás notado si has leído las otras respuestas a esta pregunta. También tienen un montón de propiedades y operaciones con nombres especiales. Tanto es así que he hecho un Glosario y lo he incluido al final de esta respuesta. Por favor, consúltalo si te sientes confundido por alguno de los términos que utilizo o por la forma en que los uso.
Cuando hablo de un árbol (en lugar de un gráfico de árbol), me refiero a un árbol jerárquico como el que se utiliza habitualmente en informática, con una raíz, ramas, hijos, etc. Cuando me refiero a "un corte en el subárbol $b$ " de un árbol, me refiero a cortar $b$ de la raíz (y por tanto del resto) del árbol o cortar una arista perteneciente al subárbol $b$ . En la teoría de grafos, el peso de un corte es el número de aristas cortadas, pero con los árboles, ese número es siempre 1, por lo que el peso de un corte no es tan interesante, y a veces uso "peso del corte" como abreviatura para referirme al tamaño del subárbol creado por el corte.
Siempre que hablo de peso o pesadez, me refiero al número de nodos de algún subárbol o al número de nodos que quedan en el otro árbol tras eliminar uno o varios subárboles. Esto se corresponde con el orden de la componente del gráfico del árbol representada por esos nodos del árbol.
No voy a intentar demostrarlo todo. Empecé a hacerlo pero se me hizo largo y tedioso. Déjame un comentario si crees que he afirmado algo que no es cierto y quizá añada una prueba más adelante.
- El objetivo es encontrar la trisección óptima de un Árbol Gráfico en $O(n \log n)$ tiempo.
- "Óptimo" se define como $\max(abc)$ , donde $a$ , $b$ y $c$ son los tamaños de los tres componentes que quedan después de la trisección.
Parte 1: Convertir el gráfico de árbol en el tipo de árbol adecuado
- Encontrar el vértice $r$ de manera que los componentes de $G-r$ todos tienen un orden como máximo $n/2$ . Está garantizado que habrá al menos $1$ dicho vértice.
- Convertir en un árbol jerárquico enraizando el gráfico de árbol en $r$ .
El árbol resultante tiene unas propiedades estupendas. En particular, tiene un subárbol que llamaré el "subárbol pesado" que contiene tantos o más nodos que cualquier otro subárbol, pero al mismo tiempo se garantiza que tiene peso $h \le n/2$ .
Parte 2: Operar en el árbol
Encontrar la mejor bisección en $O(n)$
Podemos crear el árbol descrito anteriormente, incluyendo el cálculo del peso de cada nodo y la búsqueda del subárbol pesado, en $O(n)$ .
La bisección óptima del Árbol Gráfico se obtiene cortando la arista entre la raíz del árbol y el subárbol pesado.
Demuestre que esto es cierto
Ten en cuenta que para los enteros, $x > y \iff (x-1)(y+1) > xy$ .
Por definición, el peso del subárbol pesado $h \le n/2$ y, por tanto, el número de nodos que no están en él son $r = n - h$ . También, $h \ge$ el peso de cualquier otro subárbol $s$ . Dado que cualquier subárbol de un árbol es más pequeño que el árbol completo, $h > s \iff h >$ el peso de cualquier subárbol de $s$ . Así que $r \ge h \ge s \ge$ cualquier otro subárbol. Así que $rh$ es el producto del $2$ números más grandes y cercanos que podemos hacer y, por lo tanto, es lo mejor que podemos hacer.
Encontrar la mejor trisección en $O(n \log n)$
La otra pieza que faltaba
La mejor trisección requiere al menos $1$ (En realidad, debido a la simetría, esto es un poco exagerado. Formalmente, al menos $1$ elemento del conjunto de trisecciones equivalentemente óptimas puede hacerse mediante un corte en el subárbol pesado).
El mismo razonamiento que prueba el corte del subárbol pesado $h$ hace la mejor bisección demuestra que cualquier trisección hecha con 2 cortes no en $h$ no empeoraría por el recorte $h$ en lugar de cualquiera de los otros 2 cortes.
Dejemos que $h$ sea el peso del subárbol pesado, $x$ y $y$ sea el peso de los 2 subárboles cortados para hacer una trisección y dejando $r = n - (h + x + y)$ nodos que no están en el subárbol pesado o en $x$ o $y$ . $$h(r+x)y \ge (h+r)xy$$ $$h(r+x) \ge (h+r)x$$ $$hr + hx >= hx + rx$$ $$hr >= rx$$ $$h >= x $$
Dado que elegimos específicamente $h \ge$ todos los valores posibles de $x$ podemos contar con poder encontrar una trisección óptima limitándonos a trisecciones que incluyan al menos $1$ corte en el subárbol pesado. (Obsérvese que $y$ se elimina por completo de la ecuación, por lo que no importa si $x$ es mayor o menor que $y$ lo que significa que no tenemos que preocuparnos de que $y$ puede ser un subárbol de $x$ . Si $y$ era un subárbol de $x$ , lo que nos impide mantener $y$ mientras se sustituye $x$ con $h$ Podríamos sustituir $y$ con $h$ en su lugar).
Por un razonamiento similar a los argumentos de bisección y trisección anteriores, también podemos estar seguros de que si la trisección óptima requiere 2 cortes en el subárbol pesado, entonces será la bisección óptima del subárbol pesado cortada del resto del árbol. Si se hace $2$ cortes en el subárbol pesado, se está comprometiendo a $r \ge n/2$ ser $a$ el mayor de los 3 componentes de la trisección. Con $r > n/3$ quieres hacerlo más pequeño, por lo que quieres $b+c$ sea lo más grande posible, lo que significa que se quiere un corte entre el subárbol pesado y la raíz. Con esto hecho y el requisito de que el segundo corte esté en el subárbol pesado, el mejor segundo corte es por definición la bisección óptima del subárbol pesado.
Molerlo todo
Una vez establecido esto, sólo necesitamos algunas estructuras de datos sencillas. Ya hemos encontrado todos los tamaños de subárbol posibles para el árbol completo. Podemos encontrar todos los cortes posibles en el subárbol pesado y la mejor bisección del subárbol pesado en $O(n)$ .
Podemos entonces poner los tamaños de todos los subárboles que no están en el subárbol pesado en un árbol de búsqueda binario en $O(n \log n)$ . Entonces, dado un corte en el subárbol pesado, podemos encontrar el mejor corte posible que no esté en el subárbol pesado en $O(\log n)$ tiempo.
A continuación, probamos todos los $O(n)$ cortes del subárbol pesado contra todos los cortes que no están en el subárbol pesado para $O(n \log n)$ tiempo total de funcionamiento.
Luego hemos calculado todas las posibles trisecciones que no hemos descartado, y si estábamos atentos, recordamos cuál era $max(abc)$ . Hemos terminado.
Optimización para $O(n)$ tiempo total de funcionamiento
Si realmente nos importa la complejidad temporal de esto, podemos deshacernos de las ordenaciones y las búsquedas binarias a costa de aumentar el número de $O(n)$ operaciones y haciendo que la solución sea aún más molesta.
Podemos, en una $O(n)$ pasar por la estructura de datos, encontrar cualquier número que constituya la "mejor" elección según algún criterio arbitrario, siempre y cuando siempre haya una "mejor" elección o no nos importe cuál de varias elecciones igualmente buenas elegimos como "mejor", que es nuestro caso.
Dividamos el árbol completo $T$ de tamaño $n$ en el subárbol pesado $H$ y el resto del árbol $R$ . Utilizando el análisis que nos llevó a la $O(n \log n)$ solución, sólo necesitamos encontrar 10 números. Utilizaré la abreviatura "par más cercano a x" para referirme al par de números formado por el número más pequeño $\ge x$ y el mayor número $\le x$ aunque, por supuesto, los 2 números más cercanos a $x$ puede ser mayor o menor que $x$ .
- $h = |H|$ el peso de $H$
- $h_{half}$ el peso del subárbol de $H$ más cercano a $h \over 2$
- 2 pesos de los subárboles de $H$ el par más cercano a $n \over 3$ .
- 2 pesos de los subárboles de $R$ el par más cercano a $n \over 3$
- 2 pesos de los subárboles de $H$ : Para cada uno de los pesos $w$ del par de subárboles en $R$ más cercano a $n \over 3$ el peso del subárbol más cercano a $(n-w)\over 2$
- 2 pesos de los subárboles de $R$ : Para cada uno de los pesos $w$ del par de subárboles en $H$ más cercano a $n \over 3$ el peso del subárbol más cercano a $(n-w)\over 2$
La mejor trisección va a ser $h_{half}(h - h_{half})(n-h)$ o alguna combinación de 1 de los 4 subárboles de $H$ con 1 de los 4 subárboles de $R$ encontrado arriba. Como algunos de los subárboles podrían ser iguales (y lo sabríamos enseguida), no necesitamos necesariamente encontrar los 10 números. Podríamos salirnos con la suya encontrando sólo $h$ y 2 subárboles de peso exacto $n\over 3$ y no tener que buscar más. Así que encontramos de 3 a 10 números para hacer de 1 a 1+4+4 = 9 posibles particiones para intentar elegir la mejor, todo $O(n)$ o $O(1)$ operaciones, y tenemos y respuesta en $O(n)$ tiempo.
Glosario
- Un árbol jerárquico de tamaño o peso $n$ = un gráfico de árbol $G = (V,E)$ de orden $n$
- es una colección de $n$ nodos = $|G|$ = $|V|$ vértices (singular: vértice) conectados por
- $n-1$ conexiones = $|V|-1$ bordes = $|E|$ bordes,
- de tal manera que cada nodo es alcanzable = conectado a cada otro nodo por un único camino, lo que significa que no hay
- nodos con más de un padre = ciclos.
- El $order$ de un componente o un gráfico es el número de vértices que contiene.
- El $degree$ de un nodo/vértice es el número de conexiones al nodo = aristas que tienen el vértice como punto final.
- El $weight$ de un nodo en un árbol jerárquico es el número de nodos del subárbol rooteado en ese nodo, que es igual al número de descendientes del nodo más $1$ para el propio nodo.
- Algo es más pesado que otra cosa si tiene mayor peso. Del mismo modo, se dice que algo con menos peso es más ligero.
- Un componente es un grafo conectado máximo = un conjunto de vértices tal que hay un camino desde cualquier vértice a cualquier otro vértice. Un grafo en forma de árbol es un tipo especial de grafo que es un componente único sin ciclos ni aristas paralelas. Tiene el mínimo número de aristas posible para que los vértices sean un único componente (completamente conectado).
- Un árbol jerárquico es una especialización de un gráfico de árbol. Tiene un único nodo designado como raíz. Todos los nodos, excepto la raíz, tienen exactamente $1$ padre. (La raíz no tiene un padre). Todos los nodos conectados a un nodo, excepto su padre, se dicen hijos de ese nodo y tienen ese nodo como padre. Así, para todos los nodos, si $a$ es $b$ de los padres, $b$ es $a$ y todos los nodos conectados a la raíz son hijos de la misma. Se dice que los hijos están por debajo de sus padres y que los padres están por encima de sus hijos. Todos los hijos de un nodo determinado se llaman hermanos entre sí. Los hijos de un nodo se denominan nietos, y para describir el resto de las relaciones se utilizan nombres coherentes con la genealogía, con la salvedad de que un nodo sin hijos se denomina hoja. Los descendientes de un nodo son sus hijos y todos sus descendientes.
- Un subárbol de un árbol es un árbol propiamente dicho, formado por un nodo y todos sus descendientes. El subárbol correspondiente al nodo raíz es el árbol completo.
- Un gráfico de árbol puede tener su raíz en un vértice. Cualquier nodo/vértice puede ser elegido como raíz.
- Para rootear un gráfico de árbol en un vértice $r$ significa mapearlo en un árbol jerárquico con $r$ como raíz, todos los vecinos de $r$ como hijos de la raíz y todos sus padres la raíz, y luego recursivamente para cada vértice $v$ empezando por los hijos de la raíz, designando a los vecinos de $v$ excepto su padre como sus hijos y designando al padre de sus hijos como $v$ , recurriendo a $v$ hasta que todos los vértices estén mapeados. Al final, cada vértice del grafo del árbol corresponde exactamente a 1 nodo del árbol, y cada arista del grafo del árbol corresponde exactamente a 1 conexión padre-hijo, por lo que pueden considerarse intercambiables.
- Cuando se desconecta un nodo de su padre, se dice que se convierte en la raíz de un subárbol disjunto, y se puede denominar el subárbol rooteado en ese nodo.
- Del mismo modo, cuando se corta una arista de un gráfico de árbol, se divide (o $bisect$ ) en $2$ gráficos de árbol, uno que contiene los vértices que permanecen conectados al vértice de un lado de la arista (y todas las aristas que los conectan) y los que permanecen conectados al vértice del otro lado de la arista (y todas las aristas que los conectan). Esto se llama $bisection$ . Eliminar $2$ bordes y tú $trisect$ el árbol (a $trisection$ ).
- Un nodo sin hijos no tiene descendientes y se llama hoja. Un vértice de grado $1$ se llama hoja. Es posible rootear un gráfico de árbol en un vértice de grado $1$ pero en un árbol jerárquico la raíz no se considera una hoja a menos que sea el único nodo del árbol.
2 votos
No es relevante para la pregunta planteada, pero: a menudo en situaciones como ésta puede haber algoritmos que encuentran una solución aproximadamente correcta que son más rápidos que cualquier cosa que garantice encontrar la solución correcta. ¿Le interesan esas soluciones o realmente necesita la optimalidad?
0 votos
@DanielMcLaury Ya sé cómo hacer una buena suposición, es decir, encontrar una solución aproximadamente correcta, así que para los fines de esta pregunta sólo estoy interesado en algo que garantice la optimalidad.
0 votos
Parece que no es muy fácil encontrar un algoritmo requerido. Así que si usted no va a obtener una respuesta aquí le recomiendo que haga esta pregunta en Teoría CS.SE .
0 votos
Estoy confundido. Acerca de buscar un bi sección: ¿Buscas el número mínimo de aristas a cortar para dividir el árbol en dos bosques? $F_1$ y $F_2$ tal que $F_1$ y $F_2$ tienen el mismo número de vértices (dentro de 1). O estás buscando la única arista a cortar para acercarte lo más posible a una bisección, cortando sólo una arista. El título y la introducción dicen que estás buscando lo primero, pero el resto del texto dice que estás buscando lo segundo.
0 votos
@Mike Para un árbol, cualquier arista que cortes bisectará el árbol en un bosque de 2 árboles, y cualquier 2 aristas cortadas trisectarán el árbol. De todas formas te he cambiado el título.
0 votos
@OldPro Efectivamente, un corte de arista dará 2 componentes conectados, 2 cortes de arista darán 3. Si no me equivoco, sin embargo, una "bisección" a menudo (por lo general?) Se refiere a un corte en el que hay el mismo número de vértices en ambos lados (a menos de uno) y una "trisección" un corte en el que hay el mismo número de vértices en los tres lados (a menos de uno). En cualquier caso, entiendo lo que pregunta, gracias por la aclaración.