我们给了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。
从一个开始检查每个可能的组合将花费大量时间。什么是解决问题的有效算法?
答案 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)
这相当于找到与图中最小周期和弦的和弦。一个非常天真的算法是:
检查边缘的移除是否导致包含与边缘对应的顶点的循环。如果是,则记下最小周期的长度。