这是对任意二进制DAG LMC的多项式时间算法(尝试)。G
这回答了问题3。(很抱歉提前进行凌乱的记录。:))
首先,“永远”丢弃无法到达的任何顶点。我们不关心这些,因为他们没有任何的一部分小号 - 牛逼路径。sst
接下来,定义子DAG 和B,最初为空。然后,对于所有顶点v ∈ g ^ - { 小号,牛逼},ABv∈G−{s,t}
测试是否存在从到t的路径。如果是这样,加v来一个。如果不加v给乙。vtvAvB
让的边缘和乙是每一组内的那些由顶点诱导(现在,忽略来自任何边缘小号到甲,从阿到吨,以及从甲到乙 ;还注意到没有从边缘乙至吨由施工)。ABsAAtABBt
然后,计算的传递闭包。即,我们有兴趣找到一些顶点集{ a ∗ },这些顶点是sub-DAG A的“叶” 。A{a∗}A
修复任何这样。注意,必须有从向边一个*到牛逼。这是因为,通过构造,(ⅰ)有一个小号 - 吨通过路径一个*,(ⅱ)不存在从路径一个*通过乙,和(iii)因为甲本身是DAG和一个*是叶的甲,没有来自路径一个*通过的另一顶点阿到吨。a∗a∗tsta∗a∗BAa∗Aa∗At
现在,还必须有一个从每个顶点到B中的某个顶点的有向边,或者某些{ a ∗ }具有一个到t的边。在这两种情况下,我们被允许删除任何一个* → 牛逼边缘。{a∗}B{a∗}ta∗→t
如果= 1,则无论是必须从独特删除边缘一个* → 吨,或有在前面的一个顶点小号 - 吨含有路径一个*具有两个路径吨一个通- 一个*和一个直接。如果后者可能会保留,我们记录一个* → 牛逼并继续“向后贪婪”(关于这个详情见下文)。|{a∗}|a∗→tsta∗ta∗a∗→t
如果> 1,那么我们必须从{ a ∗ } → t删除所有边,否则有一些边的传递闭包中的更早部分,它使所有路径从通过断开到。|{a∗}|{a∗}→tA s { a ∗ } tk<|{a∗}|As{a∗}t
这就是我们使用图是二进制DAG 的事实。G
考虑的前身集合。由于这些顶点中的每个顶点最多具有两个度数,因此恰好有三种情况:{a∗}
情况1.前任在具有某个顶点的边缘,而在B中具有某些顶点的边缘。{a∗}B
在这种情况下,它不会不管我们是否删除的前身边缘在点或从顶点在边缘{ 一* }到牛逼。因此,我们可以“跳过”该顶点(并检查后向路径是否与{ a ∗ }中的另一个顶点的路径合并)。{a∗}{a∗}t{a∗}
壳体2甲前身具有外边缘,以在顶点和另一前身{ 一个* }。{a∗}{a∗}
在这种情况下,我们必须删除到t的两条边,或者我们可以删除s到前一条断开两条路径的路径中的一条较早的边。{a∗}ts
情况3.前任的边在两个顶点。{a∗}
这是相同的情况下,2不要紧,我们是否删除该前任的边缘之一,并从相应的其他边缘到牛逼,或两者从边缘{ 一* }到牛逼。我们只是想知道我们是否可以断开路径小号通过这个前身为牛逼与先前在路径中的单刃从小号的前身。{a∗}t{a∗}tsts
总而言之,当我们在可传递闭合中回溯前任时,我们可以贪婪地跟踪“迄今为止最好的”选择。也就是说,在每一步中,我们都有一个显而易见的选择,即删除一些边缘,但是我们要等着看是否有更好的选择。找到更好的选项后,我们可以“忘记”上一个选项。因此,在每个前任层的贪婪选择就足够了(只要我们等到最后才做出任何选择)。A
O(|E|)O(|E|2)O(|E|)。
O(|V|⋅(|V|+|E|))O(|V|3)O(|E|2)O(|V|2+|E||V|+|V|3+|E|2)=O(|V|3+|E|2)
st