ค้นหาชุดของการจับคู่ขอบสูงสุด


13

พิจารณากราฟที่ไม่ได้ทำการเชื่อมต่อ ชุดการจับคู่ของขอบบนกราฟนี้ถูกกำหนดให้เป็นชุดของขอบเช่นว่าไม่มีสองขอบในส่วนแบ่งชุดจุดสุดยอดที่พบบ่อย ตัวอย่างเช่นรูปด้านซ้ายแสดงชุดการจับคู่เป็นสีเขียวในขณะที่รูปขวาแสดงถึงชุดการจับคู่ที่ไม่ใช่สีแดง

ป้อนคำอธิบายรูปภาพที่นี่

มีการกล่าวถึงชุดการจับคู่maximally matchingหรือmaximal matchingถ้าไม่สามารถเพิ่มขอบของกราฟลงในชุดการจับคู่ได้ ดังนั้นทั้งสองตัวอย่างข้างต้นไม่ใช่ชุดการจับคู่สูงสุด แต่ชุดทั้งสองด้านล่างเป็นสีน้ำเงินเป็นการจับคู่สูงสุด โปรดทราบว่าการจับคู่สูงสุดไม่จำเป็นต้องซ้ำกัน นอกจากนี้ยังไม่มีข้อกำหนดว่าขนาดของการจับคู่สูงสุดที่เป็นไปได้สำหรับกราฟนั้นเท่ากับการจับคู่อื่นป้อนคำอธิบายรูปภาพที่นี่

เป้าหมายของความท้าทายนี้คือการเขียนโปรแกรม / ฟังก์ชั่นเพื่อค้นหาการจับคู่สูงสุดของกราฟ

อินพุต

สมมติว่าจุดยอดทั้งหมดของกราฟป้อนข้อมูลมีจำนวนเต็มต่อเนื่องเริ่มต้นที่ค่าจำนวนเต็มเริ่มต้นที่คุณเลือก ขอบถูกอธิบายโดยคู่เลขจำนวนเต็มที่ไม่เรียงลำดับซึ่งหมายถึงจุดยอดที่ขอบเชื่อมต่อ ตัวอย่างเช่นกราฟที่แสดงด้านบนสามารถอธิบายได้ด้วยชุดของขอบที่ไม่เรียงลำดับดังต่อไปนี้ (สมมติว่าจำนวนของจุดยอดเริ่มต้นที่ 0):

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

อีกทางเลือกหนึ่งในการอธิบายกราฟคือผ่านรายการ adjacency นี่คือตัวอย่างของรายการ adjacency สำหรับกราฟด้านบน:

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

โปรแกรม / ฟังก์ชั่นของคุณจะต้องใช้กราฟอินพุตจากแหล่งใด ๆ (stdio, พารามิเตอร์ฟังก์ชั่น ฯลฯ ) คุณสามารถใช้สัญลักษณ์ใดก็ได้ที่ต้องการตราบใดที่ไม่มีการสื่อสารข้อมูลที่ไม่สำคัญเพิ่มเติมกับโปรแกรมของคุณ ตัวอย่างเช่นการมีพารามิเตอร์พิเศษเพื่อแสดงว่าจำนวนของขอบอินพุตนั้นเป็นที่ยอมรับได้อย่างสมบูรณ์ ในทำนองเดียวกันการส่งผ่านหลายเซ็ตของขอบรายการคำนำหรือเมทริกซ์ adjacency ก็ดี

คุณอาจจะ:

  1. กราฟเชื่อมต่ออยู่ (เช่นเป็นไปได้ที่จะไปถึงจุดสุดยอดใดก็ตามที่มีจุดเริ่มต้นใด ๆ )
  2. มีอย่างน้อยหนึ่งขอบ
  3. ขอบไม่เคยเชื่อมต่อจุดยอดโดยตรงกับตัวเอง (เช่นขอบ(1,1)จะไม่ได้รับเป็นอินพุต) โปรดทราบว่ารอบยังคงเป็นไปได้ (เช่น: กราฟด้านบน)
  4. คุณอาจต้องการให้จุดยอดอินพุทเริ่มต้นที่ดัชนีใด ๆ (เช่นจุดยอดแรกอาจเป็น 0, 1, -1 และอื่น ๆ )
  5. การกำหนดหมายเลข Vertex จะเพิ่มขึ้นตามลำดับจากดัชนีเริ่มต้นที่คุณเลือก (เช่น: 1,2,3,4,...หรือ0,1,2,3,...)

เอาท์พุต

โปรแกรม / ฟังก์ชั่นของคุณควรแสดงรายการขอบที่แสดงถึงชุดการจับคู่สูงสุด ขอบถูกกำหนดโดยจุดยอดสองจุดที่ขอบนั้นเชื่อมต่อ อดีต เอาท์พุทสำหรับชุดสีฟ้าซ้าย (โดยใช้การสั่งซื้อจุดยอดอินพุทตัวอย่าง):

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

โปรดทราบว่าลำดับของจุดยอดไม่สำคัญ ดังนั้นเอาต์พุตต่อไปนี้จะอธิบายชุดการจับคู่ที่เหมือนกัน:

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

เอาต์พุตอาจเป็น stdout, ไฟล์, ค่าส่งคืนของฟังก์ชัน

ตัวอย่าง

นี่คือตัวอย่างเล็ก ๆ น้อย ๆ (ใช้รูปแบบรายการ adjacency) 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

เกณฑ์การให้คะแนน

นี่คือรหัสกอล์ฟ รหัสที่สั้นที่สุดชนะ ช่องโหว่มาตรฐานใช้ คุณสามารถใช้บิวด์อินที่ต้องการได้

คำตอบ:


9

CJam (16 ตัวอักษร)

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

การสาธิตออนไลน์

นี่เป็นวิธีโลภที่สะสมขอบซึ่งไม่มีจุดยอดเหมือนกันกับขอบที่สะสมไว้ก่อนหน้านี้


ผมค่อนข้างมั่นใจว่านี้ล้มเหลวในตัวอย่างที่สามให้แทนชุดสูงสุด[[0 1] [3 4]] [[0 2] [1 4] [3 5]](ฉันเพิกเฉยต่อ(1, 1)ขอบที่ดูเหมือนจะอยู่ในนั้นโดยไม่ได้ตั้งใจ)
ETHproductions

@ETHproductions คุณสร้างความสับสนให้มากที่สุดด้วยจำนวนสูงสุด
Peter Taylor

3
Dangit ขอโทษด้วย ... ฉันจะฝากความคิดเห็นไว้เพื่อช่วยคนอื่นที่สับสนถ้าคุณไม่รังเกียจเพราะนี่เป็นปัญหาที่เกิดขึ้นซ้ำ ๆ :-P
ETHproductions

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 ไบต์

บันทึกแล้ว 3 ไบต์ด้วย @MartinEnder

FindIndependentEdgeSet

สิ่งนี้รับอินพุตเป็นGraphวัตถุ (กำหนดเป็นGraph[{1<->2,2<->3,1<-3>}]ฯลฯ )


@#&คุณไม่จำเป็นต้อง
Martin Ender

@MartinEnder ขอบคุณ
Scott Milner

pfft import solve_problem; run(). ตอนนี้มีคนต้องการเขียนปลั๊กอินสำหรับ Wolfram ที่ใช้ใน codegolf challenge URL และแสดงผลลัพธ์ที่ต้องการ Golfเรียกมันว่า
Draco18 ไม่ไว้วางใจ 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 ค่อนข้างกระชับในด้านนี้
แม่ชีที่รั่วไหล

ผมไม่ได้หมายความว่า แต่แรกรหัสปลายในขณะที่สองสิ้นสุดลงในรหัส≠∧ L≠
Erik the Outgolfer

โดยไม่ต้องมีจะมีนัย.ในตอนท้าย วิธีทั้งหมดที่นี่คือที่.จะไม่ถูกแทรกในตอนท้าย
แม่ชีที่รั่วไหล

Lเป็นตัวแปรชั่วคราวที่จะใช้ที่ไหนเลยด้วยเหตุนี้ความสามารถในการถูกมองข้าม
แม่ชีที่รั่วไหล

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

ฉันคิดว่าฉันจะให้วิธีการแบบวนซ้ำและการขโมยเคล็ดลับการแยก @ ETH ของการผลิตของ @ ETH ทำให้เกิดการตัดคำตอบของเขา!

ฉันไม่ใช่คนแรกที่อ่านคำถามเดิมผิดและฉันกำลังจะส่งฟังก์ชันเรียกซ้ำต่อไปนี้ซึ่งพบว่ามีชุดของการจับคู่สูงสุดแทนที่จะเป็นชุดของการจับคู่สูงสุด ฉันรู้!

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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.