给定一棵树,生成其Prüfer代码


10

一个Prüfer代码是整数的唯一序列,它表示一个特定的树。

您可以使用以下来自维基百科的算法找到一棵树的Prüfer代码:

考虑一个标记树T与顶点{1, 2, ..., n}。在步骤i处,删除标签最小的叶子,并将Prüfer序列的第i个元素设置为该叶子邻居的标签。

(请注意,由于它是一片叶子,因此只有一个邻居)。

当图形中仅保留两个顶点时,应停止迭代。

任务

给定一个带有标签的树作为输入输出,其Prüfer代码。您可以以任何合理的方式接受输入。例如邻接矩阵或您的语言内置图形表示。(您可能不接受输入作为Prüfer代码)。

这是 因此,您应该以最小化源中的字节为目标。

测试用例

这是一些ASCII输入,其输出如下。您不需要支持这样的ASCII输入。

    3
    |
1---2---4---6
    |
    5

{2,2,2,4}

1---4---3
    |
5---2---6---7
|
8

{4,4,2,6,2,5}

5---1---4   6
    |       |
    2---7---3

{1,1,2,7,3}

我们可以接受一棵有根的树作为输入吗?
xnor

我们可以像[[2,1],[2,3],[2,5],[2,4,6]]第一种情况那样接受输入吗?(即每个分支)
HyperNeutrino

@xnor是的,您可以
Ad Hoc Garf Hunter'May

1
我觉得输入带有指向根的边或路径的输入是对Prüfer代码的预计算。无论哪种方式,我认为您都应该更清楚“您可以以任何合理的方式输入(您不能以Prüfer代码输入)”。
xnor

@xnor哦,我不明白Hyper Neutrino在问什么。
Ad Hoc Garf Hunter's

Answers:


9

Mathematica,34个字节

<<Combinatorica`
LabeledTreeToCode

有人必须做...。

加载Combinatorica程序包后,该函数LabeledTreeToCode希望将树输入作为无向图,并带有明确列出的边和顶点;例如,第二个测试用例中的输入可能是Graph[{{{1, 4}}, {{4, 3}}, {{4, 2}}, {{2, 5}}, {{2, 6}}, {{6, 7}}, {{5, 8}}}, {1, 2, 3, 4, 5, 6, 7, 8}]


5
当然,有内置的功能可以做到这一点。> _>
HyperNeutrino

4

Python 3中,136个 131 127字节

def f(t):
 while len(t)>2:
  m=min(x for x in t if len(t[x])<2);yield t[m][0];del t[m]
  for x in t:m in t[x]and t[x].remove(m)

将输入作为邻接矩阵。第一个例子:

>>> [*f({1:[2],2:[1,3,4,5],3:[2],4:[2,6],5:[2],6:[4]})]
[2, 2, 2, 4]

好吧,我失败了……
HyperNeutrino

@HyperNeutrino您快了约4秒!
L3viathan '17

呵呵 大约是原来的2.7倍!:D gg
HyperNeutrino

1
del存在吗?> _>
HyperNeutrino

1
@WheatWizard您对分号是正确的,但是在Python 3中混合使用制表符和空格是一个错误
。– L3viathan

2

果冻,31 个字节

FĠLÞḢḢ
0ịµÇHĊṙ@µÇCịṪ,
WÇÐĿḢ€ṖṖḊ

单子链接,该链接以任意顺序(以及每个方向)获取节点对列表(定义边),并以列表形式返回Prüfer代码。

在线尝试!

怎么样?

FĠLÞḢḢ - Link 1, find leaf location: list of edges (node pairs)
F      - flatten
 Ġ     - group indices by value (sorted smallest to largest by value)
  LÞ   - sort by length (stable sort, so equal lengths remain in prior order)
    ḢḢ - head head (get the first of the first group. If there are leaves this yields
       -   the index of the smallest leaf in the flattened version of the list of edges)

0ịµÇHĊṙ@µÇCịṪ, - Link 2, separate smallest leaf: list with last item a list of edges
0ị             - item at index zero - the list of edges
  µ            - monadic chain separation (call that g)
   Ç           - call last link (1) as a monad (index of smallest leaf if flattened)
    H          - halve
     Ċ         - ceiling (round up)
      ṙ@       - rotate g left by that amount (places the edge to remove at the right)
        µ      - monadic chain separation (call that h)
         Ç     - call last link (1) as a monad (again)
          C    - complement (1-x)
            Ṫ  - tail h (removes and yields the edge)
           ị   - index into, 1-based and modular (gets the other node of the edge)
             , - pair with the modified h
               -    (i.e. [otherNode, restOfTree], ready for the next iteration)

WÇÐĿḢ€ṖṖḊ - Main link: list of edges (node pairs)
W         - wrap in a list (this is so the first iteration works)
  ÐĿ      - loop and collect intermediate results until no more change:
 Ç        -   call last link (2) as a monad
    Ḣ€    - head €ach (get the otherNodes, although the original tree is also collected)
      ṖṖ  - discard the two last results (they are excess to requirements)
        Ḋ - discard the first result (the tree, leaving just the Prüfer Code)

1

05AB1E,29个字节

[Dg#ÐD˜{γé¬`U\X.å©Ï`XK`ˆ®_Ï]¯

在线尝试!

说明

[Dg#                           # loop until only 1 link (2 vertices) remain
    ÐD                         # quadruple the current list of links
      ˜{                       # flatten and sort values
        γé                     # group by value and order by length of runs
          ¬`U                  # store the smallest leaf in X
             \X                # discard the sorted list and push X
               .å©             # check each link in the list if X is in that link
                  Ï`           # keep only that link
                    XK`ˆ       # add the value that isn't X to the global list
                        ®_Ï    # remove the handled link from the list of links
                           ]   # end loop
                            ¯  # output global list

1

Clojure,111个字节

#(loop[r[]G %](if-let[i(first(sort(remove(set(vals G))(keys G))))](recur(conj r(G i))(dissoc G i))(butlast r)))

要求输入为哈希图,以“类叶子”标签作为键,以“类根”标签作为值。例如:

{1 2, 3 2, 5 2, 4 2, 6 4}
{1 4, 3 4, 4 2, 8 5, 5 2, 7 6, 6 2}

在每次迭代中,它找到未被其他任何节点引用的最小键,将其添加到结果中,r并将该节点从图定义中删除Gif-let当去到别的情况下G是空的,作为first回报nil。同样,最后一个元素也必须被删除。


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.