我有数组A和B.我必须找到数组B的最大匹配,这样B [i]的每个索引都可以匹配A [j]的任何索引,当且仅当 A [j]时]!= B [i]和A [j]先前未匹配。例如:
A = {1 2 3 4}
B = {2 2 3 4}
Maximum Matching is 4 A[0]=B[3] , A[1]=B[2] , A[2]=B[1], A[3]=B[0]
A = {1 1 2}
B = {1 1 2}
Maximum Matching 2 A[0]=B[2] , B[1]=No Matching , A[2]=B[0]
我知道这是最大的二分问题,但问题是 A = B <= 10 ^ 3且A [i],B [i] <10 ^ 6 的长度。哪个会超时我的二分解决方案。有没有更好的解决方案?
代码:
public static boolean is_match(int curr) {
for(int i = 0; i < A.length; i++) {
if(A[i] != curr && !V[i]) {
V[i] = true;
if(P[i] < 0 || is_match(P[i])) {
P[i] = curr;
return true;
}
}
}
return false;
}
我为每个B调用此函数:
for(int i:B){
V = new boolean[n]
if(is_match(i)) match++;
}
如何改进我的解决方案?
答案 0 :(得分:1)
此问题可视为最大流量问题。
因此,条件是A[j]!=B[i] and A[j] is not previously matched
,因此知道i
中的索引A
是否与j
中的k
或B
匹配B[j] == B[k]
并不重要。
因此,不是将图表表示为2*n
节点的二分,而是每个节点代表数组A和B中的索引,我们可以将问题表示为具有一个源节点,一个汇聚节点和表示A和B的唯一值的节点列表,以及节点a
(表示A中的a
值)到源节点的容量是A
中具有的a
的索引量价值b
。类似地,映射到下沉节点的节点b
的容量将等于B中的索引数具有值A = {1, 1, 2, 2}
。从A到B的有效节点之间的容量是无穷大。
例如,使用数组B = {1, 2, 2, 3, 3, 3, 3}
和alphaChar
因此,我们创建了一个包含源节点和汇聚节点的流程图。
此外,对于阵列A,我们创建了两个额外的节点,一个用于值1,另一个用于值2.源节点将连接到这两个节点。
对于节点B,我们创建三个节点,一个用于值1,一个用于值2,一个用于值3.
现在,源节点将仅连接到阵列A的节点,容量相等:2表示节点表示值1(因为阵列A中有两个1),2表示节点表示值2(有两个)阵列A)中的2。
Sink节点只能连接到阵列B的节点,容量为: 节点1表示值1(阵列B中只有1个);节点2表示值2(阵列B中有两个2),节点4表示值3(阵列B中有4个)。
从阵列A到B的有效节点之间的连接将具有无限容量。
现在剩下的工作就是运行典型的最大流算法。
答案 1 :(得分:1)
我认为您可以将原始算法调整为O(n ^ 2)。
对于A中的每个节点:(即此循环将重复n次)
a
。扫描所有先前的匹配项,查看是否有任何A节点(!=a
)与B节点(!=a
)匹配。如果是这样,请更改此前一个节点的映射,并为新节点腾出空间。 O(n)这是整体O(n ^ 2)。
当B中不等于a
的所有节点都已映射到A中等于a
的节点时,第二遍将无法找到匹配项。这意味着有太多的节点等于a
,因此解决方案是可能的,并且问题不可能每次都满足。
答案 2 :(得分:0)
二分匹配问题可以通过所谓的Hungarian algorithm解决,也可以建模为maximum flow problem;也许这些算法的实现更快。
作为流动问题的建模如下工作; A
构成左侧分区的项目,B
的项目构成右侧分区。在分区之间,在节点之间创建容量1
的边缘,当且仅当它可以匹配它们时。将源节点放在最左侧,将其连接到左侧分区的每个节点,边缘为容量1
;还将一个终端节点放在最右边,将其连接到右侧分区的每个节点,边缘容量为1
。如果从源到终端的流量最大化,则通过在中间选择具有非零流量值的这些边缘,它将对应于最大匹配。