Hier ist (ein Versuch) ein Polynom-Algorithmus für LMC auf beliebigen binären DAGs .G
Dies beantwortet Frage 3. (Entschuldigen Sie die unordentliche Beschreibung im Voraus. :))
Werfen Sie zunächst "für immer" alle Scheitelpunkte aus, von denen aus Sie nicht erreichen können . Wir kümmern uns nicht um diese, da sie nicht Teil irgendeines sind s - t Weg.sst
Definieren Sie als Nächstes die Sub-DAGs und B , die anfangs leer sind. Dann gilt für alle Eckpunkte v ∈AB ,v∈G−{s,t}
Testen Sie, ob es einen Pfad von nach t gibt . Wenn ja, fügen Sie v aufvtv . Wenn nicht, füge v zu B hinzu .AvB
Die Kanten von und B sollen die Kanten sein, die durch die Scheitelpunkte in jeder Menge induziert werden (vorerst ignorieren Sie alle Kanten von s nach A , von A nach t und von A nach B)ABsAAtAB ; beachten Sie auch, dass es keine Kanten von nach t von gibt Konstruktion).Bt
Dann berechnet die transitive Hülle von . Wir sind nämlich daran interessiert, eine Reihe von Eckpunkten zu finden {A , die die "Blätter" der Sub-DAG A sind .{a∗}A
Repariere so . Beachten Sie, dass es eine gerichtete Kante von a ∗ bis t geben muss . Dies liegt daran, dass konstruktionsbedingt (i) es einen s - t - Pfad durch a ∗ gibt , (ii) es keine Pfade von a ∗ durch B gibt und (iii) da A selbst eine DAG ist und a ∗ ein Blatt ist von A gibt es keinen Weg von a ∗ durch einen anderen Scheitelpunkt von A nach t .a∗a∗tsta∗a∗BAa∗Aa∗At
Jetzt muss es auch eine gerichtete Kante von jedem Scheitelpunkt in zu einem Scheitelpunkt in B geben , oder einige der { a ∗ } müssen eine einzelne Kante zu t haben . In jedem Fall werden wir alle löschen erlaubt eine * → t Rand.{a∗}B{a∗}ta∗→t
Wenn = 1, dann müssen wir entweder die Kante aus dem eindeutigen a ∗ → t löschen , oder es gibt einen Scheitelpunkt im s - t - Pfad, der ein ∗ enthält , das zwei Pfade zu t hat - einen durch ein ∗ und einen direkt. Für den Fall, dass Letzteres zutrifft, nehmen wir ein ∗ → t auf und gehen "gierig rückwärts" vor (Details dazu weiter unten).|{a∗}|a∗→tsta∗ta∗a∗→t
Wenn > 1, dann müssen wir entweder alle Kanten aus { a ∗ } → t löschen , oder es gibt eine gewisse Anzahl von Kanten k < | { a ∗ } | früher in der transitiven Schließung von A , die alle Pfade von s durch die { a ∗ } zu t trennen .|{a∗}|{a∗}→tk<|{a∗}|As{a∗}t
Hier verwenden wir die Tatsache, dass der Graph eine binäre DAG ist.G
Betrachten Sie die Menge der Vorgänger von . Da jeder dieser Eckpunkte höchstens zwei Ausmaße hat, gibt es genau drei Fälle:{a∗}
Fall 1 ein Vorgänger hat eine außerKante bis zu einem gewissen Eckpunkt in und ein Out-Rand zu einem gewissen Vertex in B .{a∗}B
In diesem Fall spielt es keine Rolle, ob wir die Kante vom Vorgänger zum Scheitelpunkt in oder die Kante vom Scheitelpunkt in { a ∗ } bis t löschen . Daher können wir diesen Scheitelpunkt "überspringen" (und prüfen, ob der Rückwärtspfad mit einem Pfad eines anderen Scheitelpunkts in { a ∗ } verschmilzt ).{a∗}{a∗}t{a∗}
Fall 2. Ein Vorgänger hat eine Außenkante zu einem Scheitelpunkt in und einen anderen Vorgänger von { a ∗ } .{a∗}{a∗}
In diesem Fall müssen wir entweder beide Kanten von bis t löschen, oder wir können eine einzelne frühere Kante im Pfad von s zum Vorgänger löschen , die beide Pfade trennt.{a∗}ts
Fall 3. Ein Vorgänger hat eine Außenkante zu zwei Eckpunkten in .{a∗}
Dies ist identisch mit Fall 2. Es spielt keine Rolle , ob wir einen der diesen Vorgängers Kanten löschen und die entsprechenden anderen Kanten von zu t oder beide der Kanten von der { eines * } zu t . Wir wollen nur wissen, ob wir den Pfad von s durch diesen Vorgänger zu t mit einer einzelnen Kante früher auf dem Pfad von s zum Vorgänger trennen können .{a∗}t{a∗}tsts
Insgesamt können wir, während wir die Vorgänger im transitiven Abschluss von rückwärts durchgehen , die "bisher besten" Entscheidungen gierig verfolgen. Das heißt, wir haben bei jedem Schritt eine offensichtliche Wahl, bei der einige Kanten gelöscht werden, aber wir möchten abwarten, ob eine bessere Option verfügbar ist. Sobald eine bessere Option gefunden wurde, können wir die vorherige Option "vergessen". Daher genügt eine gierige Wahl auf jeder Ebene der Vorgänger (solange wir bis zum Ende warten, um uns auf eine Wahl zu verpflichten).A
Therefore, with some basic memoization, the time and space complexities of this process appear to be at most O(|E|). This leaves out the fact that, while we can locally/greedily identify when we have found a "cheaper choice," it's a priori unclear which previously-recorded edges to remove. Therefore, we record the order in which we check edges as we go. Upon finding a better option, we repeat the search up to this point in order to find which previously-recorded edges to remove. The total time complexity of this step is O(|E|2) and space complexity O(|E|).
Altogether, the time complexity is O(|V|⋅(|V|+|E|)) for initialization, plus O(|V|3) for the transitive closure, plus O(|E|2) for the search. The total time is O(|V|2+|E||V|+|V|3+|E|2)=O(|V|3+|E|2).
Upon completing the process, we obtain the minimum set of edges required to disconnect s from t while preserving at least one out-edge of every vertex in the graph (or we discover that a solution is impossible along the way, and abort).