총 토폴로지 정렬 수


11

주어진 DAG (지향 비순환 그래프)의 경우, 각 위상 정렬은 모든 정점의 순열이며 , DAG의 모든 모서리 (u, v) 에 대해 u 가 순열에서 v 앞에 나타납니다 .

주어진 DAG의 총 토폴로지 종류 수를 계산해야합니다.

규칙

  • 인코딩에서 유용한 계산을 수행하지 않는 한 임의의 형식을 사용하여 인접 행렬, 인접 목록 또는 가장자리 목록과 같은 그래프를 나타낼 수 있습니다. 유용한 경우 입력에 꼭짓점 개수 또는 꼭짓점 목록과 같은 항목이있을 수도 있습니다.
  • 입력의 그래프가 항상 DAG라고 가정 할 수 있습니다 (사이클이 없음).
  • 프로그램은 모든 입력에 대해 이론적으로 작동해야합니다. 그러나 언어의 기본 정수 유형이 오버플로되면 실패 할 수 있습니다.
  • 꼭짓점의 이름은 모든 유형의 연속 값일 수 있습니다. 예를 들어 숫자는 0 또는 1로 시작합니다 (물론이 숫자에 코드를 저장하지 않은 경우에만 해당).
  • 이것은 코드 골프입니다. 가장 짧은 코드가 승리합니다.

이것은 다른 형식의 동일한 입력입니다. 당신의 프로그램은 그것들을 모두 받아 들일 필요는 없습니다. 꼭짓점은 항상 0부터 시작하는 정수입니다.

Adjacency list:
[ [1 2 3 5] [2 4] [] [2] [] [3] ]
Adjacency matrix:
[ [0 1 1 1 0 1] [0 0 1 0 1 0] [0 0 0 0 0 0] [0 0 1 0 0 0] [0 0 0 0 0 0] [0 0 0 1 0 0] ]
Edge list:
6 [ [0 1] [0 2] [0 3] [0 5] [1 2] [1 4] [3 2] [5 3] ]

이 이미지에 표시된 그래프입니다.

예제 그래프

출력은 다음과 같아야합니다.

9

토폴로지 종류는 다음과 같습니다.

[0 1 4 5 3 2]
[0 1 5 4 3 2]
[0 1 5 3 4 2]
[0 1 5 3 2 4]
[0 5 1 4 3 2]
[0 5 1 3 4 2]
[0 5 1 3 2 4]
[0 5 3 1 4 2]
[0 5 3 1 2 4]

함수? 전체 프로그램? 어느 한 쪽?
isaacg

@isaacg 어느 쪽이든.
jimmy23013

답변:


4

CJam-25

q~{_f{1$-_j@j@&!*}_!+:+}j

user23013의 큰 도움으로 :)

온라인으로 사용해보십시오

설명:

일반적인 알고리즘은 xnor의 Python 솔루션 과 동일 합니다. .
여기서 중요한 것은 j재귀를 메모 하는 연산자입니다. 초기 값에 대한 매개 변수, 값 또는 배열 (f (0), f (1) 등)과 재귀를 정의하는 블록을 사용합니다. j운영자는 동일한 블록에 재귀 (및 memoized) 통화를 수행하기위한 블록 내부에 다시 사용된다. 여러 매개 변수와 함께 사용할 수도 있지만 여기서는 그렇지 않습니다.
user23013의 큰 혁신은 인접 목록을 초기 값 배열로 사용하여 다른 데이터 유형으로 j를 사용하는 것입니다.

q~             read and evaluate the input (vertex list followed by adjacency list)
{…}j           run the block on the vertex list, doing memoized recursion
                and using the adjacency list for initial values
    _          copy the vertex list
    f{…}       for each vertex and the vertex list
        1$-    copy the vertex and remove it from the list
                Python: "V-{v}"
        _j     copy the reduced list and call the j block recursively
                this solves the problem for the reduced vertex list
                Python: "f(G,V-{v})"
        @j     bring the vertex to the top of the stack and call the j block recursively
                in this case, it's called with a vertex rather than a list
                and the memoized value is instantly found in the list of initial values
                effectively, this gets the list of vertices adjacent to the current vertex
                Python: "G[v]"
        @&     bring the reduced list to the top of the stack and intersect
        !*     multiply the number of topological sorts of the reduced vertex list
                with 1 if the intersection was empty and 0 if not
                Python: equivalent to "*(V-G[v]==V)"
               after this loop we get an array of sub-results for the reduced vertex lists
    _!+        add 1 or 0 to the array if the array was empty or not
                because we want to get 1 for the empty array
                Python: equivalent to "V<{0}or"
    :+         add the numbers in the array
                Python: "sum(…)"

1
입력에서 꼭짓점 목록을 명시 적으로 허용하도록 편집되었습니다. 이제 25 바이트 입니다.
jimmy23013

@ user23013 어떤 종류의 마법입니까? : 오
SE 악이기 때문에 aditsu 종료

7

파이썬, 58

f=lambda G,V:V<{0}or sum(f(G,V-{v})*(V-G[v]==V)for v in V)

입력은 인접 사전 G과 정점 세트 로 구성됩니다.V .

G = {0:{1,2,3,5}, 1:{2,4}, 2:set(), 3:{2}, 4:set(), 5:{3}, 6:set()}
V = {0,1,2,3,4,5}

코드는 재귀 적입니다. 세트 V는 여전히 방문해야하는 모든 노드를 저장합니다. 각각의 잠재적 다음 노드를 들어, 우리는 남아있는 정점으로, 그것을 지적하지 않는 경우 확인하여 적합성을 확인 V-G[v]==V하는 것이 확인 VG[v]해체 있습니다. 적합한 모든 정점에 대해 제거 된 위상 정렬 수를 추가합니다. 기본적으로 빈 세트는 1을 제공합니다.


에지리스트를 사용하지 않는 경우 +1
jimmy23013

5

Mathematica, 80 57 51 바이트

Count[Permutations@#,l_/;l~Subsets~{2}~SubsetQ~#2]&

정의를 매우 간단하게 구현합니다. 나는 단지 모든 순열을 생성하고 유효한 수를 세고 있습니다. 순열이 유효한지 확인하기 위해 순열에 모든 정점 쌍을 얻습니다. 편리 Subsets[l,{2}]하게는 모든 쌍을 제공 할뿐만 아니라 그들이 필요로하는 순서를 유지 l합니다.

위의 정점 목록과 가장자리 목록을 기대하는 함수입니다.

f[{1, 2, 3, 4, 5, 6}, {{1, 2}, {1, 3}, {1, 4}, {1, 6}, {2, 3}, {2, 5}, {4, 3}, {6, 4}}]

당신은 함수를 호출하는 경우 f.

나는 이것을 골프하려고 시도하거나 나중에 다른 접근법을 사용할 것입니다.


2

Pyth, 27 바이트

Mlf!sm}_dHfq2lYyTfqSZUZ^UGG

2 입력 함수를 정의합니다 g. 첫 번째 입력은 꼭짓점의 수이고, 두 번째 입력은 지정된 가장자리의 목록입니다.

테스트하려면 :

Code:
Mlf!sm}_dHfq2lYyTfqSZUZ^UGGghQeQ

Input:
6, [ [0, 1], [0, 2], [0, 3], [0, 5], [1, 2], [1, 4], [3, 2], [5, 3] ]

여기에서 시도하십시오.


@ user23013의 ^UGG모든 G항목 목록 을 생성 하는 표현식에서 Boht count 및 list가 사용되고 range(len(G))있습니다.
isaacg

[0, 1, ...]입력에 직접 사용하면 더 짧을 까요?
jimmy23013

@ user23013 아니, 같은 길이 될 것이다 : ^GlG대를 ^UGG.
isaacg 2016

2

하스켈, 102 (107) 100 89 85 바이트

import Data.List
(%)=elemIndex
n#l=sum[1|p<-permutations[0..n],and[u%p<v%p|[u,v]<-l]]

입력은 가장 높은 정점 번호 (0으로 시작)와 가장자리 목록이며 가장자리는 두 요소 목록입니다. 사용 예 :5 # [[0,1], [0,2], [0,3], [0,5], [1,2], [1,4], [3,2], [5,3]]

작동 원리 : 모든 순열 계산 p모든 가장자리가있는 정점의 [u,v]만족을 :의 위치 u에서이 p위치보다 작 v에서 p. 그것은 정의의 직접적인 구현입니다.

편집 : 내 첫 번째 버전은 토폴로지 정렬 자체를 반환했지만 그 수는 많지 않았습니다. 고쳤다.

편집 II : 정점이 연결되지 않은 그래프에서는 작동하지 않았습니다. 고쳤다.


정점 만
있고

@ user23013 : 이제 정점이 연결되지 않은 그래프에서 작동합니다. 심지어 더 짧아졌습니다.
nimi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.