所以我遇到了一个问题,其中有' n'飞行员和' m'飞机。每个飞行员都有一张他可以飞的飞机清单。一名飞行员一次只能飞一架飞机。您必须确定可以同时飞行的最大飞机数量。标准的二分匹配问题(我后来发现)。
在比赛中,我想出了一个贪婪的算法如下:
虽然图中有飞机:
1)选择一个可以通过最少数量的飞行员飞行的飞机
2)贪婪地将飞行员分配给该飞机(来自可以飞行的飞机)
3)从图表中删除飞机和分配的飞行员
一般来说,对于二分匹配问题,我提出以下算法:
虽然二分图的右侧集中有节点:
1)从右侧设置中选择一个具有最小传入度
的节点2)贪婪地将它与左边的任何节点(有一个边缘)相匹配
3)从图中删除这两个节点(这也将涉及减少该节点有边缘的右侧所有节点的传入程度)
我在数学上并不熟练地证明这种算法的正确性,并且在经过大量思考之后我还没有能够提出一个反例。 所以我的具体问题是,这是一个标准的或已知的算法,还是我犯了一些我看不到的明显错误?
如果您有这样的想法,请随时编辑我的问题以使其更清晰。谢谢。
答案 0 :(得分:2)
贪婪的方法不适用于二分匹配。您可能已经猜到的问题是“选择左侧的任何节点”。
这是一个例子 - 左边的节点是A,B,C和D,右边的节点是x,y,z,t。将A,B,C中的每一个与x,y,z(此处为9个边)连接,然后将D与t连接,将A与t连接。因此,右侧有3个节点,其中3度(x,y,z)为1,而度量为2(t)的节点为1。因此,您选择t并在左侧随机选择一个节点 - 这可能是A或D.问题是,如果选择A,则最大匹配将为3,而实际答案为4(通过选择D)
答案 1 :(得分:2)
反例:
a1 a2 a3 a4 a5
p1 x x
p2 x x x x
p3 x x x x
p4 x
p5 x x x
首先选择a5。随机选择可能是p5的飞行员。如果是,p4没有飞机。
答案 2 :(得分:0)
没有理由使用贪心算法!如果你无法证明它的正确性,那就错了。例如,您的贪心算法失败,因为它的输出取决于顶点的顺序。
您应该阅读这篇文章:https://en.wikipedia.org/wiki/Matching_%28graph_theory%29#Algorithms_and_computational_complexity
例如,有一个有效的二分图算法:Hopcroft-Karp
答案 3 :(得分:0)
我还对通过Google Code Jam 2018第二轮测试的二分匹配做出了贪婪的解决方案,总体上非常好, 但并非完全没有缺陷 。它将通过Jur的测试案例。与作者不同的是,我在所有节点之间进行选择-在这种情况下,飞行员和飞机都可以选择。因此,在Jur的情况下,p4将是我的首选。如果我有几个具有相似重要性的顶点, 在这些节点中,我选择链接到连接最少的节点的任何节点。我连接到连接最少的对方。
我制作了一个程序来测试它与带有流量的二部匹配,发现有时确实出错了。有趣的是,它在随机生成的数据上出错的频率在很大程度上取决于维度。对于n=m=20
,在220
中有200k
个随机生成的案例有误,但版本更准确。对于n=m=400
,在1
的{{1}}中是错误的。
但这并不比基于流的经典解决方案快。
这是一个错误的案例
500k
3 - 1 - -
1 3 - - -
- 1 3 1 1
- - 1 3 1
1 1 - - -
代表由我的贪婪算法选择的边缘,3
代表未被选择的边缘。 Here's my code in C++。