找到最大数k,使得对于k对的所有组合,我们在每个组合中具有k个不同的元素

时间:2012-05-10 12:41:50

标签: algorithm

我们给了N对。每对包含两个数字。我们必须找到最大数K,使得如果我们采用来自给定N对的J(1 <= J <= K)对的任何组合,我们在所有那些选择的J对中具有至少J个不同的数。我们可以有不止一对。

例如,考虑对 (1,2) (1,2) (1,2) (7,8) (9,10) 对于这种情况,K = 2,因为对于K> 1。 2,如果我们选择三对(1,2),我们只有两个不同的数字,即1和2。

从一个开始检查每个可能的组合将花费大量时间。什么是解决问题的有效算法?

4 个答案:

答案 0 :(得分:0)

似乎与MinCut / MaxFlow有关。这是尝试将其缩小为MinCut / MaxFlow:

- Produce one vertex for each number
- Produce one vertex for each pair
- Produce an edge from number i to a pair if the number is present in the pair, weight 1
- Produce a source node and connect it to all numbers, weight 1 for each connection
- Produce a sink node and connect it to all numbers, weight 1 for each connection

对此运行MaxFlow应该为您提供数字K,因为任何三对总共只包含两个数字的对,将被数字的出局边缘上的约束“阻止”。

我不确定这是否是最快的解决方案。我想在那里可能还有一个隐藏在一个补体中。在那种情况下,有一种贪婪的方法。但是我找不到你正在构建的集合的matroid属性的证明。

答案 1 :(得分:0)

我在这方面取得了一些进展,但还不是一个有效的解决方案。但它可能指明了方向。

制作一个点为对的图形,如果它们共用一个数字,则连接任意一对点。然后对于任何子图,其中的数字数是顶点数减去边数。因此,您的问题与定位边缘多于顶点的最小子图(如果有)相同。

具有相同边数和顶点数的最小子图是一个循环。因此,我们正在寻找的图形是共享一个或多个顶点的2个周期,或者是通过路径连接的2个周期。没有其他可能的最小类型。

您可以使用广度优先搜索轻松定位和枚举周期。可能会有很多,但这是可行的。有了这个,您可以查找这些子类型的子图。 (枚举最小周期,寻找共享点或连接的对。)但不保证是多项式。我怀疑这将是一个非常好的东西,但最坏的情况是非常糟糕的。然而,这可能比你现在正在做的更有效。

我一直认为某种广度优先的搜索可以在多项式时间内找到它们,但我一直都没有看到确切的方法。

答案 2 :(得分:0)

创建一个图表,每个数字都有一个顶点,每对数字都有一个边缘。

如果这个图是一个链或一个树,我们有“数字”的数量,等于“对”的数量加上一个,从这个图中删除任意数量的边之后,我们从来没有得到比边更少的顶点。

现在向此链/树添加一个循环。顶点和边数相等。从此图中删除任意数量的边后,我们再次得到的顶点不会比边更少。

现在添加任意数量的断开连接的组件,每个组件不应包含多个循环。再一次,在删除任意数量的边之后,我们永远不会获得比边更少的顶点。

现在为任何断开连接的组件添加第二个循环。删除所有其他组件后。最后,我们有更多的边缘而不是顶点(更多的对比数字)。

所有这些导致得出的结论是,K + 1恰好是最小可能子图中的边数,包括两个周期,可能还有一个连接这些周期的链。

算法:

对于每个连接的组件,使用Floyd-Warshall算法找到每个节点的最短周期。

然后对于每个非重叠循环(在单个分量中),使用Dijkstra算法,从在一个循环中具有至少3个边缘的任何节点开始,找到到达其他循环的最短路径;并计算两个周期和最短路径的长度之和,连接它们。对于每个重叠的循环对,只需计算它们的边数。

现在找到所有这些子图的最小长度。并减去1。

如果图中至少有一个双循环分量,则上述算法计算K.如果没有这样的成分,K = N。

答案 3 :(得分:0)

这相当于找到与图中最小周期和弦的和弦。一个非常天真的算法是:

检查边缘的移除是否导致包含与边缘对应的顶点的循环。如果是,则记下最小周期的长度。

相关问题