
    9 jE                         S r SSKrSS/r\R                  R                  S5      S 5       rS r\R                  R                  S5      \R                  S 5       5       r	g)	z6
Algorithms for computing distance measures on trees.
    Ncentercentroiddirectedc                    [        U R                  5      nUR                  5        VVs1 s H  u  p#US:X  d  M  UiM     nnn[        U5      S:  a  U(       a  [	        5       nU Hz  nX	 U R                  U5       H`  nXq;  a  M
  X==   S-  ss'   X   =nS:X  a  UR                  U5        M3  US:X  d  M;  [        U5      S:w  d  ML  [        R                  " S5      e   M|     Un[        U5      S:  a	  U(       a  M  [        U5      n	U	S:X  a  U(       a  U	S;  a  [        R                  " S5      e[        U5      $ s  snnf )a  Returns the center of an undirected tree graph.

The center of a tree consists of nodes that minimize the maximum eccentricity.
That is, these nodes minimize the maximum distance to all other nodes.
This implementation currently only works for unweighted edges.

If the input graph is not a tree, results are not guaranteed to be correct and while
some non-trees will raise an ``nx.NotATree`` exception, not all non-trees will be discovered.
Thus, this function should not be used if caller is unsure whether the input graph
is a tree. Use ``nx.is_tree(G)`` to check.

Parameters
----------
G : NetworkX graph
    A tree graph (undirected, acyclic graph).

Returns
-------
center : list
    A list of nodes forming the center of the tree. This can be one or two nodes.

Raises
------
NetworkXNotImplemented
    If the input graph is directed.

NotATree
    If the algorithm detects the input graph is not a tree. There is no guarantee
    this error will always raise if a non-tree is passed.

Notes
-----
This algorithm iteratively removes leaves (nodes with degree 1) from the tree until
there are only 1 or 2 nodes left. The remaining nodes form the center of the tree.

This algorithm's time complexity is ``O(N)`` where ``N`` is the number of nodes in the tree.

Examples
--------
>>> G = nx.Graph([(1, 2), (1, 3), (2, 4), (2, 5)])
>>> nx.tree.center(G)
[1, 2]

>>> G = nx.path_graph(5)
>>> nx.tree.center(G)
[2]
      r   zinput graph is not a tree>   r   r   )
dictdegreeitemslenset	neighborsaddnxNotATreelist)
Gcenter_candidates_degreenoder
   leaves
new_leavesleafneighborcddnns
             {/root/GenerationalWealth/GenerationalWealth/venv/lib/python3.13/site-packages/networkx/algorithms/tree/distance_measures.pyr   r      s)   b  $AHH~'?'E'E'GW'G|t6UV;d'GFW &
'!
+U
D(.KK-;(2a724>>D1DNN8,QY3'?#@A#E++&ABB .   &
'!
+ 	$%A	Qv!6/ kk566())1 Xs
   D;D;c                 d   US0nU/n[         R                  " X5       HO  u  pEUS   U:w  a,  UR                  5       nX#S   ==   X&   -  ss'   US   U:w  a  M,  UR                  U5        SX%'   MQ     [         R                  R                  [        U5      5       H  u  pTX$==   X%   -  ss'   M     U$ )a  Return a `dict` of the size of each subtree, for every subtree
of a tree rooted at a given node.

For every node in the given tree, consider the new tree that would
be created by detaching it from its parent node (if any). The
number of nodes in the resulting tree rooted at that node is then
assigned as the value for that node in the return dictionary.

Parameters
----------
G : NetworkX graph
   A tree.

root : node
   A node in `G`.

Returns
-------
s : dict
   Dictionary of number of nodes in every subtree of this tree,
   keyed on the root node for each subtree.

Examples
--------
>>> _subtree_sizes(nx.path_graph(4), 0)
{0: 4, 1: 3, 2: 2, 3: 1}

>>> _subtree_sizes(nx.path_graph(4), 2)
{2: 4, 1: 2, 0: 1, 3: 1}

r   )r   	dfs_edgespopappendutilspairwisereversed)r   rootsizesstackparentchild
descendants          r   _subtree_sizesr+   Z   s    @ 1IEFEa.Bi6!J) 11 Bi6! 	U / **8E?;% <L    c                 :  ^ ^ [         R                  " T 5      (       d  [         R                  " S5      eS[         R                  R	                  T 5      p![        T U5      mT R                  5       nU U4S jnU" X5      n[        UTU   -
  TR                  US5      5      US-  :  a5  X%p!U" X5      n[        UTU   -
  TR                  US5      5      US-  :  a  M5  U/T R                  U5       Vs/ s H  ofU:w  d  M
  TU   US-  :X  d  M  UPM     sn-   $ s  snf )a  Return the centroid of an unweighted tree.

The centroid of a tree is the set of nodes such that removing any
one of them would split the tree into a forest of subtrees, each
with at most ``N / 2`` nodes, where ``N`` is the number of nodes
in the original tree. This set may contain two nodes if removing
an edge between them results in two trees of size exactly ``N /
2``.

Parameters
----------
G : NetworkX graph
   A tree.

Returns
-------
c : list
   List of nodes in centroid of the tree. This could be one or two nodes.

Raises
------
NotATree
    If the input graph is not a tree.
NotImplementedException
    If the input graph is directed.
NetworkXPointlessConcept
    If `G` has no nodes or edges.

Notes
-----
This algorithm's time complexity is ``O(N)`` where ``N`` is the
number of nodes in the tree.

In unweighted trees the centroid coincides with the barycenter,
the node or nodes that minimize the sum of distances to all other
nodes. However, this concept is different from that of the graph
center, which is the set of nodes minimizing the maximum distance
to all other nodes.

Examples
--------
>>> G = nx.path_graph(4)
>>> nx.tree.centroid(G)
[1, 2]

A star-shaped tree with one long branch illustrates the difference
between the centroid and the center. The center lies near the
middle of the long branch, minimizing maximum distance. The
centroid, however, limits the size of any resulting subtree to at
most half the total nodes, forcing it to remain near the hub when
enough short branches are present.

>>> G = nx.star_graph(6)
>>> nx.add_path(G, [6, 7, 8, 9, 10])
>>> nx.tree.centroid(G), nx.tree.center(G)
([0], [7])

See Also
--------
:func:`~networkx.algorithms.distance_measures.barycenter`
:func:`~networkx.algorithms.distance_measures.center`
center : tree center
zprovided graph is not a treeNc                 b   >^  [        U 4S jTR                  U5       5       TR                  S S9$ )Nc              3   6   >#    U  H  oT:w  d  M
  Uv   M     g 7f)N ).0xprevs     r   	<genexpr>4centroid.<locals>._heaviest_child.<locals>.<genexpr>   s     7)1$YQQ)s   		)keydefault)maxr   get)r3   r%   r   r&   s   ` r   _heaviest_child!centroid.<locals>._heaviest_child   s*    7D)7UYYPT
 	
r,   r   r   )
r   is_treer   r"   arbitrary_elementr+   number_of_nodesr8   r9   r   )r   r3   r%   
total_sizer:   hcr2   r&   s   `      @r   r   r      s   D ::a==kk899rxx11!4$1d#E""$J

 
	$B
j5;&		"a(8
9JN
JdT( j5;&		"a(8
9JN
J 6;;t$$aT	eAh*q.6P$   s   2	D?
DD)
__doc__networkxr   __all__r"   not_implemented_forr   r+   _dispatchabler   r0   r,   r   <module>rF      s}      j)I* *I*X*Z j)R  *Rr,   