DAGは推移的な削減ですか?


11

この課題の目的は、有限有向非巡回グラフ(DAG)を与えられ、グラフが推移的縮小であるかどうかを判断することです。

DAGと推移的削減の概要:

DAGは有向エッジを持つグラフです(つまり、そのエッジ上を一方向にのみ移動できます)。そのため、グラフ上の開始ノードがある場合、開始ノードに戻ることはできません(つまり、サイクルはありません)。

開始ノードがある場合、任意の正の数のエッジを介してグラフ内の別の終了ノードに移動できる場合、その終了ノードは開始ノードから到達可能として定義されます。一般的なDAGには、開始ノードからターゲット終了ノードまでの複数のパスが存在する場合があります。たとえば、次のひし形グラフをご覧ください。

ここに画像の説明を入力してください

ノードに到達するためにDからA、あなたはパスを取ることができますA->B->DA->C->D。したがって、Dから到達可能ですA。ただし、node Bから開始するノードに到達するために使用できるパスはありませんC。したがって、node Bはnode から到達できませんC

グラフのすべての開始ノードの到達可能ノードのリストとして、グラフの到達可能性を定義します。したがって、同じダイアモンドグラフの例では、到達可能性は次のとおりです。

A: [B, C, D]
B: [D]
C: [D]
D: []

上記のグラフと同じ到達可能性を持つ別のグラフを以下に示します。

ここに画像の説明を入力してください

ただし、この2番目のグラフには、元のグラフよりも多くのエッジがあります。グラフの推移的削減は、エッジの数が最も少なく、元のグラフと同じ到達可能性を持つグラフです。したがって、最初のグラフは2番目のグラフの推移的な減少です。

有限DAGの場合、推移的縮約が存在することが保証されており、一意です。

入力

入力は「リストのリスト」であり、外部リストは頂点の数の長さを持ち、各内部リストは関連するノードを離れるエッジの数の長さであり、宛先ノードのインデックスを含みます。たとえば、上記の最初のグラフを説明する1つの方法は次のとおりです(ゼロベースのインデックス付けを想定)。

[[1, 2], [3], [3], []]

任意の整数値で最初のノードのインデックス作成を開始できます(0または1ベースのインデックス作成など)。

入力は、必要な入力ソース(stdio、関数パラメーターなど)から取得できます。追加情報が提供されない限り、正確な入力形式を自由に選択できます。たとえば、stdioから入力を取得する場合、各行を関連ノードのエッジのリストにすることができます。例:

1 2
3
3
'' (blank line)

各隣接リストのインデックスは必ずしもソートされているわけではなく、2つのノードを接続する複数のエッジが存在する可能性があります(例:)[[1,1],[]]。入力グラフが弱く接続されており、サイクルが含まれていない(つまり、DAGである)と仮定できます。

出力

与えられた入力DAGが推移的還元である場合、出力は真実であり、そうでない場合は偽の値です。これは、任意のシンク(stdio、戻り値、出力パラメーターなど)に対して行うことができます

すべての例では、0ベースのインデックス付けを使用しています。

[[1,2],[3],[3],[]]
true

[[1,2,3],[3],[3],[]]
false

[[1,1],[]]
false

[[1,2,3,4],[5,6,7],[5,8,9],[6,8,10],[7,9,10],[11,12],[11,13],[12,13],[11,14],[12,14],[13,14],[],[],[],[]]
true

[[5,6,7],[2,3,0,4],[5,8,9],[6,8,10],[7,9,10],[11,12],[11,13],[12,13],[11,14],[12,14],[13,14],[],[],[],[]]
true

[[5,6,7],[2,3,0,4,14,5,7],[5,8,9],[6,8,10],[7,9,10],[11,12],[11,13],[12,13],[11,14],[12,14],[13,14],[],[],[],[]]
false

[[5,6,7],[2,3,0,4],[5,8,9],[6,8,10],[7,9,10,14],[11,12],[11,13],[12,13],[11,14],[12,14],[13,14],[],[],[],[]]
false

[[1,3],[2],[3],[]]
false

得点

これはコードゴルフです。バイト単位の最小コードが優先されます。コードは妥当な時間内に完了する必要があります(使用しているハードウェアで最大10分)。標準の抜け穴が適用されます。必要なビルトインを使用できます。


入力の接続性について仮定を立てることはできますか?(すべてのテストケースをチェックしたわけではありませんが、それらはグラフの複数の切断された部分をカバーしていますか?)
マーティンエンダー

正しい言語であると信じているもので更新されました。
helloworld922

大丈夫だと思います。また、グラフが弱く接続されていると言うこともできます。
マーティンエンダー

回答:


5

Ruby、101 97バイト

各ノードからリーチを計算し、他のノードのいずれかを介して子ノードに到達できるかどうかを考慮する単純なアプローチ。巡回グラフでは一見失敗しますが、DAGの定義は、とにかく巡回すべきではないことを意味します。

オンラインでお試しください!

->g{r=->i{i|i.map{|j|r[g[j]||[]]}.inject([],:|)}
g.all?{|e|e==e&e&&e.none?{|i|r[e-[i]].index i}}}

4

Mathematica、95 82バイト

@MartinEnderにより13バイトが保存されました

#~IsomorphicGraphQ~TransitiveReductionGraph@#&@Graph[x=0;##&@@Thread[++x->#]&/@#]&

無名関数。ネストされたリストを(1から始まる)入力として受け取り、出力として返すTrueFalse、または出力として受け取ります。ここでの主な解決策は、#~IsomorphicGraphQ~TransitiveReductionGraph@#&特定のグラフがその推移的縮小と同型かどうかをテストする46バイトです。残りは入力をGraphオブジェクトに変換します。


3

CJam(41バイト)

q~:A_,{{Af=e__&}%_}*]:.|A.&A:$:e`e_2%1-*!

オンラインデモテストハーネス

解剖

q~:A      e# Parse input and store in A
_,{       e# Loop V times
  {       e#   Extend adjacency list representation of G^i to G^(i+1)
    Af=   e#   by extending each path by one edge
    e__&  e#   and flattening. NB :| would be shorter but breaks for empty lists
  }%
  _       e#   Duplicate, so that we build up G^2, G^3, ..., G^n
}*]       e# Gather in a single array
:.|       e# Fold pointwise union, giving the reachability from each vertex by
          e# paths of length > 1
A.&       e# Pointwise intersect with the paths of length 1
          e# We hope to get an array of empty arrays

          e# Handle the awkward special case of duplicate edges:
A:$       e# Sort each adjacency list
:e`       e# Run-length encode each adjacency list
e_2%      e# Extract only the run lengths
1-        e# Discard the 1s - so we now have an empty array unless there's a dupe

*         e# Join. We hope to be joining an array of empty arrays by an empty array
          e# giving an empty array
!         e# Check that we get a falsy value (i.e. the empty array)

3

ゼリー、20バイト

ị³$ÐĿ€ị@Fœ&¥";œ-Q$€E

1ベースのインデックスを使用します。オンラインでお試しください!

緩い概要

     €                for each vertex,
ị³$ÐĿ                   compute its reach.
        Fœ&¥"         intersect each vertex's lists of children and
      ị@                children's reaches.
             ;        then concatenate the list of intersections with
              œ-Q$€     all duplicate edges in the original graph.
                   E  are all elements equal? checks that all are empty lists,
                        meaning empty intersections and no duplicates.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.