找到一组最大匹配边


13

考虑一个连接的无向图。甲边缘的匹配组在此图被定义为一组边,使得在该组共享的任何两个边缘公共顶点的。例如,左图表示绿色的匹配集,而右图表示红色的不匹配集。

在此处输入图片说明

匹配集称为maximally matchingmaximal matching如果不可能将图的另一条边添加到匹配集,则为。因此,以上两个示例都不是最大匹配集,但是下面两个蓝色的集合都是最大匹配。请注意,最大匹配不一定是唯一的。此外,不要求图形的每个可能最大匹配的大小都应等于另一个匹配。在此处输入图片说明

挑战的目标是编写程序/函数以找到图形的最大匹配。

输入值

假设输入图的所有顶点都有一些连续的整数编号,这些编号从您选择的任何起始整数值开始。一条边由表示该边连接的顶点的无序整数对来描述。例如,上面显示的图形可以使用以下无序边集来描述(假设顶点的编号从0开始):

[(0,1), (0,2), (1,3), (1,4), (2,3), (3,4), (3,5), (5,6)]

描述图的另一种方法是通过邻接表。这是上图的邻接表示例:

[0:(1,2), 1:(0,3,4), 2:(0,3), 3:(1,2,4,5), 4:(1,3), 5:(3,6), 6:(5)]

您的程序/函数必须从任何来源(stdio,函数参数等)获取图形作为输入。只要没有其他无关紧要的信息传达给您的程序,您就可以使用所需的任何符号。例如,一个额外的参数表示输入边的数量是完全可以接受的。类似地,传入无序的边,邻接表或邻接矩阵的多集也可以。

您可以假设:

  1. 图形已连接(例如,可以在给定任何起始顶点的情况下到达任何顶点)。
  2. 至少有一条边缘。
  3. 边永远不会将顶点直接连接到自身(例如,边(1,1)不会作为输入提供)。请注意,循环仍然可能(例如:上图)。
  4. 您可能需要输入顶点从任何索引处开始(例如,第一个顶点可以是0、1,-1等)。
  5. 顶点编号从您选择的起始索引开始按顺序增加(例如:1,2,3,4,...0,1,2,3,...)。

输出量

您的程序/函数应输出表示最大匹配集的边列表。一条边由该边连接的两个顶点定义。例如 左蓝色组的输出(使用示例输入顶点顺序):

[(1,4), (2,3), (5,6)]

注意,顶点的顺序并不重要。因此,以下输出描述了相同的匹配集:

[(4,1), (2,3), (6,5)]   

输出可能是到stdout,文件,函数返回值等。

例子

这是一些示例输入(使用邻接表格式)。这些示例碰巧开始在处计算顶点0

请注意,没有给出示例输出,而是提供了Python 3验证代码。

[0:(1), 1:(0)]

[0:(1,2), 1:(0,3,4), 2:(0,3), 3:(1,2,4,5), 4:(1,3), 5:(3,6), 6:(5)]

[0:(1,2), 1:(0,2,3,4,5), 2:(0,1), 3:(1), 4:(1), 5:(1)]

[0:(1,2), 1:(0,2,3), 2:(0,1,4), 3:(1,4,5), 4:(2,3), 5:(3)]

验证Python 3代码

这是一个Python 3验证代码,它接受图形和一组边并打印出该边是否最大匹配。此代码适用于任何顶点起始索引。

def is_maximal_matching(graph, edges):
    '''
    Determines if the given set of edges is a maximal matching of graph
    @param graph a graph specified in adjacency list format
    @param edges a list of edges specified as vertex pairs

    @return True if edges describes a maximal matching, False otherwise.
    Prints out some diagnostic text for why edges is not a maximal matching
    '''

    graph_vtxs = {k for k,v in graph.items()}
    vtxs = {k for k,v in graph.items()}

    # check that all vertices are valid and not used multiple times
    for e in edges:
        if(e[0] in graph_vtxs):
            if(e[0] in vtxs):
                vtxs.remove(e[0])
            else:
                print('edge (%d,%d): vertex %d is used by another edge'%(e[0],e[1],e[0]))
                return False
        else:
            print('edge (%d,%d): vertex %d is not in the graph'%(e[0],e[1],e[0]))
            return False
        if(e[1] in graph_vtxs):
            if(e[1] in vtxs):
                vtxs.remove(e[1])
            else:
                print('edge (%d,%d): vertex %d is used by another edge'%(e[0],e[1],e[1]))
                return False
        else:
            print('edge (%d,%d): vertex %d is not in the graph'%(e[0],e[1],e[0]))
            return False
        if(e[1] not in graph[e[0]]):
            print('edge (%d,%d): edge not in graph'%(e[0],e[1]))
            return False

    # check that any edges can't be added
    for v in vtxs:
        ovtxs = graph[v]
        for ov in ovtxs:
            if(ov in vtxs):
                print('could add edge (%d,%d) to maximal set'%(v,ov))
                return False

    return True

用法示例:

graph = {0:[1,2], 1:[0,3,4], 2:[0,3], 3:[1,2,4,5], 4:[1,3], 5:[3,6], 6:[5]}
candidate = [(0,1),(2,3)]
is_maximal_matching(graph, candidate) // False
candidate = [(0,1),(2,3),(5,6),(0,1)]
is_maximal_matching(graph, candidate) // False
candidate = [(0,1),(2,3),(5,6)]
is_maximal_matching(graph, candidate) // True

计分

这是代码高尔夫;最短的代码胜出。有标准漏洞。您可以使用所需的任何内置功能。

Answers:


9

果酱(16个字符)

{M\{_2$&!*+}/2/}

在线演示

这是一种贪婪方法,它会累积与先前累积的边没有任何顶点的边。


我很确定这在第三个示例中失败了,[[0 1] [3 4]]而不是给出了maximal set [[0 2] [1 4] [3 5]]。(我忽略了(1, 1)似乎错误地存在的边缘)
ETHproductions'Apr 26'17

@ETHproductions,您混淆了最大值和最大值。
彼得·泰勒

3
Dangit,对此感到抱歉...如果您不介意,我将只留下我的评论以帮助任何其他困惑的人,因为这似乎是一个反复出现的问题:-P
ETHproductions'Apr

7

Pyth,8个字节

ef{IsTty
       y  power set (gerenate all set of edges)
      t   remove the first one (the first one is
          empty and will cause problems)
 f        filter for sets T satisfying:
     T        T
    s         flatten
  {I          is invariant under deduplicate, i.e. contains no
              duplicating vertices, as the elements represent vertices
e         pick the last one (the power set is ordered from
          smallest to largest)

在线尝试!

眼镜

  • 输入: [(0,1), (0,2), (1,3), (1,4), (2,3), (3,4), (3,5), (5,6)]
  • 输出: [(1, 4), (2, 3), (5, 6)]

6

Wolfram语言,25 22字节

@MartinEnder节省了3个字节

FindIndependentEdgeSet

这将输入作为Graph对象(定义为Graph[{1<->2,2<->3,1<-3>}]等)。


您不需要@#&
Martin Ender

@MartinEnder谢谢。
Scott Milner

Pfft。import solve_problem; run()。现在,只需要为Wolfram编写一个插件,该插件就可以接受codegolf挑战URL并输出所需的输出。叫它Golf
Draco18s不再信任SE SE

5

Brachylog,5个字节

 ⊇.c≠∧

?⊇.cL≠   implicit ? at the beginning;
         ∧ breaks implicit . at the end;
         temporary variable inserted.
?⊇.      input is a superset of output
  .cL    output concatenated is L
    L≠   L contains distinct elements

在线尝试!

由于Brachylog从最大的子集搜索,因此可以保证这是最大的。


我认为您的解释代码与实际代码不同。
暴民埃里克(Erik the Outgolfer)

@EriktheOutgolfer那是因为我插入了我的解释中隐含的字符。原始代码在第一行。Brachylog在这方面非常简洁。
Leaky Nun

我不是那个意思,但是第一个代码以结尾≠∧,而第二个代码以结尾L≠
暴民埃里克(Erik the Outgolfer)'17

没有,最后将有一个隐式.这里的所有方法.是不要在最后插入。
Leaky Nun

L是使用不通临时变量,因此将被省略的其能力。
Leaky Nun

0

JavaScript(ES6),67个字节

let f =
a=>a.map(b=>r.some(c=>c.some(d=>~b.indexOf(d)))||r.push(b),r=[])&&r

let g = a => console.log("[%s]", f(a).map(x => "[" + x + "]").join(", "))
g([[0,1]])
g([[0,1], [0,2], [1,3], [1,4], [2,3], [3,4], [3,5], [5,6]])
g([[0,1], [0,2], [1,2], [1,3], [1,4], [1,5]])
g([[0,1], [0,2], [1,2], [1,3], [2,4], [3,4], [3,5]])

使用贪婪方法获得最大高尔夫球感。


0

JavaScript(ES6),68 66字节

f=a=>a[0]?[a[0],...f(a.filter(b=>!a[0].some(c=>~b.indexOf(c))))]:a
f=([b,...a])=>b?[b,...f(a.filter(c=>!c.some(c=>~b.indexOf(c))))]:a

我以为我会尝试递归方法,并且通过窃取@ETHproduction的设置交集技巧,我设法削弱了他的答案!

我不是第一个误解原始问题的人,我将提交以下递归函数,该函数查找最大匹配边集,而不是最大匹配边集。微妙的区别,我知道!

f=a=>a.map(([b,c])=>[[b,c],...f(a.filter(([d,e])=>b-d&&b-e&&c-d&&c-e))]).sort((d,e)=>e.length-d.length)[0]||[]

简单的递归方法。对于每个输入元素,从集合中删除所有冲突的边,并找到其余子集的匹配边的最大集合,然后在每个输入元素上找到最大结果。大集的效率有点低下(可能会提高9字节)。


0

果冻12 11字节

FQ⁼F
ŒPÇÐfṪ

在线尝试!

输入样例: [0,1],[0,2],[1,3],[1,4],[2,3],[3,4],[3,5],[5,6]

样本输出: [[1, 4], [2, 3], [5, 6]]

怎么运行的

FQ⁼F    - Helper function, returns 1 if a set of edges is non-matching
F       - Flatten input
 Q      - Remove repeated elements
  ⁼     - Return boolean value. Is this equal to
   F    - The flattened input list

ŒPÇÐfṪ - Main link.
ŒP     - Power set of input list of edges
   Ðf  - Remove all elements which return 1 if
  Ç    - (Helper function) it is a non-matching set
     Ṫ - Get the last element in the resultant list (the longest). 
           Always maximal because it is the longest, so any
           edge added would not be in this list (not matching)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.