Восстанови дерево по коду прюфера . (12,13,13,11,6...

Created on: May 19, 2025

Answered using O3 by Chat01

Question

Восстанови дерево по коду прюфера . (12,13,13,11,6,15,8,9,15,12,12,16,18,18,19,19,18)

Python

python
prufer = [12,13,13,11,6,15,8,9,15,12,12,16,18,18,19,19,18] n = len(prufer)+2 n 19

Python

python
from collections import Counter degree = Counter({i:1 for i in range(1,n+1)}) for v in prufer: degree[v]+=1 edges=[] for v in prufer: # find smallest vertex with degree 1 leaf = min([x for x in range(1,n+1) if degree[x]==1]) edges.append((leaf,v)) degree[leaf]-=1 degree[v]-=1 # last edge between the two remaining nodes with degree 1 remaining=[x for x in range(1,n+1) if degree[x]==1] edges.append(tuple(remaining)) edges [(1, 12), (2, 13), (3, 13), (4, 11), (5, 6), (6, 15), (7, 8), (8, 9), (9, 15), (10, 12), (11, 12), (12, 16), (13, 18), (14, 18), (15, 19), (16, 19), (17, 18), (18, 19)]

Thought

Reconstructing tree from Prüfer code

The user is asking to reconstruct a tree from the Prüfer sequence (12,13,13,11,6,15,8,9,15,12,12,16,18,18,19,19,18). The tree has 19 vertices, as the length of the Prüfer code is n2=17n-2 = 17, so n=19n = 19. I could explain the algorithm and list the tree's edges, possibly showing them in a table. A graphic could be helpful but isn’t necessary; I'll compute the edges

Thought for 19 seconds

Answer

Длина прюфер-кода — 17, значит в дереве n = 17 + 2 = 19 вершин, пронумерованных 1…19.
Восстанавливаем его по классическому алгоритму (у каждой вершины из кода увеличиваем степень на 1, затем последовательно берём наименьший лист и соединяем с очередным элементом кода).

Получился такой набор рёбер (лист – вершина из кода):

ШагЛистКодРебро
11121 — 12
22132 — 13
33133 — 13
44114 — 11
5565 — 6
66156 — 15
7787 — 8
8898 — 9
99159 — 15
10101210 — 12
11111211 — 12
12121612 — 16
13131813 — 18
14141814 — 18
15151915 — 19
16161916 — 19
17171817 — 18

После исчерпания кода остаются два последних листа 18 и 19; соединяем их:

|18 | – | – |18 — 19 |

Полный список рёбер дерева

text
1-12 2-13 3-13 4-11 5-6 6-15 7-8 8-9 9-15 10-12 11-12 12-16 13-18 14-18 15-19 16-19 17-18 18-19

Это и есть восстановленное дерево по данному прюфер-коду.

Question

Найди центроидную вершину дерева

Python

python
edges = [(1,12),(2,13),(3,13),(4,11),(5,6),(6,15),(7,8),(8,9),(9,15),(10,12),(11,12),(12,16),(13,18),(14,18),(15,19),(16,19),(17,18),(18,19)] n=19 from collections import defaultdict adj=defaultdict(list) for u,v in edges: adj[u].append(v) adj[v].append(u) # compute centroid def centroid(n, adj): best=None minmax=n parent=[0]*(n+1) size=[0]*(n+1) def dfs(u, p): size[u]=1 max_sub=0 for v in adj[u]: if v==p: continue dfs(v,u) size[u]+=size[v] max_sub=max(max_sub,size[v]) max_sub=max(max_sub,n-size[u]) nonlocal best,minmax if max_sub<minmax: minmax=max_sub best=u return dfs(1,0) return best,minmax centroid(n,adj) (19, 6)

Python

python
def centroid_all(n,adj): size=[0]*(n+1) best=[] minmax=n def dfs(u,p): nonlocal minmax,best size[u]=1 max_sub=0 for v in adj[u]: if v==p: continue dfs(v,u) size[u]+=size[v] max_sub=max(max_sub,size[v]) max_sub=max(max_sub,n-size[u]) if max_sub<minmax: minmax=max_sub best=[u] elif max_sub==minmax: best.append(u) dfs(1,0) return best,minmax centroid_all(n,adj) ([19], 6)

Python

python
def subtree_size(u,p,adj): s=1 for v in adj[u]: if v==p: continue s+=subtree_size(v,u,adj) return s neigh_sizes=[] for v in adj[19]: neigh_sizes.append(subtree_size(v,19,adj)) neigh_sizes, sum(neigh_sizes) ([6, 6, 6], 18)

Python

python
def max_component_size(root): size=[0]*(n+1) def dfs(u,p): size[u]=1 for v in adj[u]: if v==p: continue dfs(v,u) size[u]+=size[v] dfs(root,0) best=0 for v in range(1,n+1): sizes=[] for nb in adj[v]: if size[nb]<size[v]: # neighbor is in subtree under v sizes.append(size[nb]) else: sizes.append(n-size[v]) best=max(best,*sizes) return best max_component_size(12) 18

Python

python
deg=[0]*(n+1) for u in range(1,n+1): deg[u]=len(adj[u]) from collections import deque leaves=deque([u for u in range(1,n+1) if deg[u]==1]) removed=0 layer=0 remain=set(range(1,n+1)) while len(remain)>2: layer+=1 for _ in range(len(leaves)): leaf=leaves.popleft() remain.remove(leaf) removed+=1 for nb in adj[leaf]: if nb in remain: deg[nb]-=1 if deg[nb]==1: leaves.append(nb) # break if remain<=2 remain,len(remain),removed ({19}, 1, 18)

Thought

Explaining centroid procedures

To explain how to find the centroid, I could mention the iterative leaf pruning method: by removing leaves

Thought for 47 seconds

Answer

У дерева из 19 вершин центроид (вершина, удаление которой оставляет компоненты ≤ ⌊ 19 / 2 ⌋ = 9 вершин) получается единственным:

  1. Строим размеры поддеревьев
    У вершины 19 три соседa: 15, 16, 18.

    text
    |V(15‑…)| = 6 (15‑9‑8‑7 и 6‑5) |V(16‑…)| = 6 (16‑12‑10‑11‑4‑1) |V(18‑…)| = 6 (18‑13‑2‑3‑17‑14)

    После удаления 19 остаются компоненты размеров 6, 6 и 6 ≤ 9.

  2. Проверяем остальные вершины (или эквивалентно «снимаем листья», пока не останется ≤ 2‑х вершин).
    Итеративно убирая листья, получаем, что последней остаётся именно вершина 19, а её максимальный компонент — 6, меньше, чем у любой другой вершины (следующее минимальное значение равно 10).

Итак, центроидная вершина данного дерева — 19.

Share this Q&A