有效地选择互斥对

时间:2015-04-10 03:16:32

标签: algorithm

这是一个可以通过某种类型的暴力算法来解决的问题,但我想知道是否有一些有效的方法可以做到这一点。

假设我们有以下整数对

 (1, 3), (2, 5), (4, 7), (2, 7), (10, 9)

我们想弄清楚互斥对的最大数量是多少。

互相配对,我的意思是它们没有任何配对 常用整数。

例如,我们不能同时选择(2,5),(2,7),因为两个对都包含2个。

在上述情况下,4将是一个解决方案,因为我们可以选择以下互斥对:

      (1, 3), (2, 5), (4, 7), (10, 9)  

因此总共有4对。

我想知道是否有有效的方法。

4 个答案:

答案 0 :(得分:12)

您的问题相当于在图表上找到最大匹配。图形的节点是整数,您的对(a,b)是图形的边缘。匹配是一组成对的非相邻边,相当于说同一个整数不会出现在两条边上。

这个问题的多项式时间解决方案是Blossom algorithm also known as Edmond's algorithm.这里的答案细节太复杂了。

答案 1 :(得分:3)

编辑:由于我的误解,以前的方法不正确。

这是第二次尝试

如果我们将一对中的每个数字视为图中的节点,我们可以构建一个二分图,如果有一对包含这两个节点,则每个节点之间有边。

所以,这个问题减少了,找到maximum bipartite matching,可以使用经典Ford-fulkerson algorithm来解决。

第一个错误的方法:

我们可以通过动态编程来解决这个问题。

按对象的起点(如果绘制,按其结束点)对对进行排序。

假设我们有一个函数f,如果我们从对f(i)开始选择,i会返回最大对数。

如果我们选择一对i,我们需要检查大于i的下一个与i不重叠的最小索引。

我们有

f(i) = max(1 + f(next index not overlap i), f (i + 1))

f(i)的结果存储在表中,我们可以得到 O(n ^ 2)时间复杂度的解决方案,结果将为f(0)。< / p>

伪代码:

sort data;//Assume we have a data array to store all pairs
int[] dp;
int f(int index){
    if(index == data.length)
       return 0;  
    if(we have calculated this before)
       return dp[index];
    int nxt = -1;
    for(int i = index + 1; i < data.length; i++){
        if(data[i].start > data[index].end){
           nxt = i;
           break; 
        }
    }
    if(nxt == -1)
      return dp[index] = max(1, f(index + 1));
    return dp[index] = max(1 + f(nxt) , f(index + 1));
}

答案 2 :(得分:2)

这个问题可以用图论来重铸。图表的节点是您给出的对。如果对具有共同的数字,则连接两个节点。你的问题是找到一个最大的独立集。

最大独立集相当于找到最大集团,它既是NP完全的又是“难以近似”。但是,在这种特殊情况下,图形是一种称为“无爪”(http://en.wikipedia.org/wiki/Claw-free_graph)的特殊类型,因为如果一个节点连接到另外三个节点,那么这些节点中至少有两个必须共享一个公共数字,他们自己也是如此。

事实证明,对于无爪图的特殊情况,最大独立集问题可以在多项式时间内求解:http://en.wikipedia.org/wiki/Claw-free_graph#Independent_sets

答案 3 :(得分:1)

修改:这不会像用户98235在评论中指出的那样奏效。我会留在这里,但万一其他人有同样的想法。

如果我能正确理解问题,我认为这会有效。

伪代码:

resultList = new List of Pair
elementSet = new Set of int

for pair in inputPairs:

    if not elementSet.Contains(pair.First) and not elementSet.Contains(pair.Second):
        elementSet.Add(pair.First)
        elementSet.Add(pair.Second)
        resultList.Add(pair)

时间复杂度为O(N)。