Topológicamente clasifique este DAG para establecer un orden para sus nodos. Para cada nodo, su valor sería el número de bordes salientes de todos los nodos precedentes menos el número de bordes entrantes para todos los nodos precedentes y el nodo actual. El valor para el nodo "dominador" siempre es cero.
Después de que un nodo esté marcado como "eliminado", ponga sus predecesores y sucesores en la cola de prioridad. La prioridad está determinada por el orden de clasificación topológica. Actualice los valores para todos los nodos, siguiendo el nodo "eliminado" (agregue el número de nodos entrantes y reste la cantidad de nodos salientes para este nodo). Al mismo tiempo (en el mismo orden) el valor de decremento para cada nodo entre el nodo predecesor en la cola de prioridad y el nodo "eliminado" y el valor de incremento para cada nodo, comenzando desde el nodo sucesor en la cola de prioridad. Deténgase cuando el valor de algún nodo se reduzca a cero. Este es un nuevo nodo "dominador". Si se necesitan todos los nodos "dominator", continúe hasta el final del gráfico.
delete(delNode):
for each predecessor in delNode.predecessors: queue.add(predecessor)
for each successor in delNode.successors: queue.add(successor)
for each node in DAG:
if queue.top.priority == node.priority > delNode.priority:
++accumulator
node.value += accumulator
if node.value == 0: dominatorDetected(node)
if node.priority == delNode.priority:
accumulator += (delNode.predecessors.size - delNode.successors.size)
node.value = -1
if queue.top.priority == node.priority:
queue.pop()
if node.priority < delNode.priority:
--accumulator
if queue.empty: stop
Para el caso de múltiples fuentes, es posible utilizar el mismo algoritmo, pero mantener una lista de "valores" para cada nodo, un valor para cada fuente. La complejidad del algoritmo es O(Nodes * Sources)
, lo mismo que para la búsqueda independiente en cada una de las fuentes. Pero el programa puede hacerse más eficiente si se utiliza la vectorización. Los "valores" pueden procesarse en paralelo con las instrucciones SIMD. Los compiladores modernos pueden hacer una vectorización automática para lograr esto.
Eso significa que quiere determinar incrementalmente el corte en un gráfico cambiante? ¿Y necesitas todos esos nodos (todos los cortes) o es suficiente? – jpalecek
Sí, esa es otra forma de decirlo: detectar un corte justo antes de que ocurra (es decir, justo antes de que se elimine el último nodo que daría lugar a un corte). – Jules
Re: editar: preferiblemente todos esos cortes, pero un corte sería lo suficientemente bueno también. Los cortes deben ocurrir con relativa poca frecuencia, por lo que si sucede no es demasiado importante ejecutar un algoritmo lento para encontrar los otros cortes. – Jules