
    ܛ7iE                         d Z ddlZddgZej                  j                  d      d        Zd Zej                  j                  d      ej                  d               Z	y)	z6
Algorithms for computing distance measures on trees.
    Ncentercentroiddirectedc                 <   t        | j                        }|j                         D ch c]  \  }}|dk(  s| }}}t        |      dkD  r|rt	               }|D ]r  }||= | j                  |      D ]Y  }||vr||xx   dz  cc<   ||   x}dk(  r|j                  |       1|dk(  s7t        |      dk7  sFt        j                  d       t |}t        |      dkD  r|rt        |      }	|	dk(  r|r|	dvrt        j                  d      t        |      S c c}}w )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
             g/home/rose/Desktop/poly/venv/lib/python3.12/site-packages/networkx/algorithms/tree/distance_measures.pyr   r      s2   b  $AHH~'?'E'E'GW'G|tV6UV;d'GFW &
'!
+U
D(.KK-#;;(2a724X>>D1DNN8,QY3'?#@A#E++&ABB .   &
'!
+ 	$%A	Qv!6/ kk566())1 Xs
   DDc                 d   |di}|g}t        j                  | |      D ]O  \  }}|d   |k7  r,|j                         }||d   xx   ||   z  cc<   |d   |k7  r,|j                  |       d||<   Q t         j                  j                  t        |            D ]  \  }}||xx   ||   z  cc<    |S )a0  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%)j 11 Bi6! 	Ue / **8E?;vfu% <L    c                 "    t        j                         st        j                  d      dt         j                  j	                         }}t         |       j                         } fd} |||      }t        ||   z
  j                  |d            |dz  kD  r6||}} |||      }t        ||   z
  j                  |d            |dz  kD  r6|g j                  |      D cg c]  }||k7  s	|   |dz  k(  s| c}z   S c c}w )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                 f     t         fdj                  |      D        j                  d       S )Nc              3   .   K   | ]  }|k7  s	|  y w)N ).0xprevs     r   	<genexpr>z4centroid.<locals>._heaviest_child.<locals>.<genexpr>   s     7)1Q$YQ)s   
)keydefault)maxr   get)r3   r%   r   r&   s   ` r   _heaviest_childz!centroid.<locals>._heaviest_child   s*    7D)7UYYPT
 	
r,   r   r   )
r   is_treer   r"   arbitrary_elementr+   number_of_nodesr7   r8   r   )r   r3   r%   
total_sizer9   hcr2   r&   s   `      @r   r   r      s   D ::a=kk899rxx11!4$D1d#E""$J

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