
    h                        S r SSKJr  SSKrSSKJr  / SQr\" S5      \R                  SS j5       5       r	\" S5      \R                  SS j5       5       r
\" S	5      \" S5      \R                  " S
S9SS j5       5       5       rg)zBridge-finding algorithms.    )chainN)not_implemented_for)bridgeshas_bridgeslocal_bridgesdirectedc              #     #    U R                  5       nU(       a  [        R                  " U 5      OU n[        R                  " X1S9n[	        [
        R                  " U5      5      nUb3  UR                  [        R                  " X15      5      R                  5       nUR                  5        H9  u  pgXg4U;  d  M  Xv4U;  d  M  U(       a  [        X   U   5      S:  a  M4  Xg4v   M;     g7f)a  Generate all bridges in a graph.

A *bridge* in a graph is an edge whose removal causes the number of
connected components of the graph to increase.  Equivalently, a bridge is an
edge that does not belong to any cycle. Bridges are also known as cut-edges,
isthmuses, or cut arcs.

Parameters
----------
G : undirected graph

root : node (optional)
   A node in the graph `G`. If specified, only the bridges in the
   connected component containing this node will be returned.

Yields
------
e : edge
   An edge in the graph whose removal disconnects the graph (or
   causes the number of connected components to increase).

Raises
------
NodeNotFound
   If `root` is not in the graph `G`.

NetworkXNotImplemented
    If `G` is a directed graph.

Examples
--------
The barbell graph with parameter zero has a single bridge:

>>> G = nx.barbell_graph(10, 0)
>>> list(nx.bridges(G))
[(9, 10)]

Notes
-----
This is an implementation of the algorithm described in [1]_.  An edge is a
bridge if and only if it is not contained in any chain. Chains are found
using the :func:`networkx.chain_decomposition` function.

The algorithm described in [1]_ requires a simple graph. If the provided
graph is a multigraph, we convert it to a simple graph and verify that any
bridges discovered by the chain decomposition algorithm are not multi-edges.

Ignoring polylogarithmic factors, the worst-case time complexity is the
same as the :func:`networkx.chain_decomposition` function,
$O(m + n)$, where $n$ is the number of nodes in the graph and $m$ is
the number of edges.

References
----------
.. [1] https://en.wikipedia.org/wiki/Bridge_%28graph_theory%29#Bridge-Finding_with_Chain_Decompositions
rootN   )is_multigraphnxGraphchain_decompositionsetr   from_iterablesubgraphnode_connected_componentcopyedgeslen)Gr   
multigraphHchainschain_edgesuvs           M/var/www/html/env/lib/python3.13/site-packages/networkx/algorithms/bridges.pyr   r      s     v "J!qA##A1Fe))&12KJJr221;<AAC	6$!{)Bc!$q'lQ.$J	 s   B3C)9C)'C)c                 J     [        [        XS95        g! [         a     gf = f)aP  Decide whether a graph has any bridges.

A *bridge* in a graph is an edge whose removal causes the number of
connected components of the graph to increase.

Parameters
----------
G : undirected graph

root : node (optional)
   A node in the graph `G`. If specified, only the bridges in the
   connected component containing this node will be considered.

Returns
-------
bool
   Whether the graph (or the connected component containing `root`)
   has any bridges.

Raises
------
NodeNotFound
   If `root` is not in the graph `G`.

NetworkXNotImplemented
    If `G` is a directed graph.

Examples
--------
The barbell graph with parameter zero has a single bridge::

    >>> G = nx.barbell_graph(10, 0)
    >>> nx.has_bridges(G)
    True

On the other hand, the cycle graph has no bridges::

    >>> G = nx.cycle_graph(5)
    >>> nx.has_bridges(G)
    False

Notes
-----
This implementation uses the :func:`networkx.bridges` function, so
it shares its worst-case time complexity, $O(m + n)$, ignoring
polylogarithmic factors, where $n$ is the number of nodes in the
graph and $m$ is the number of edges.

r
   TF)nextr   StopIteration)r   r   s     r   r   r   S   s.    hWQ"#   s    
""r   weight)
edge_attrsc              #     ^^#    USLa=  U R                    H,  u  p4[        X   5      [        X   5      -  (       a  M'  X44v   M.     g[        R                  R	                  X5      mU R                    HM  u  p4[        X   5      [        X   5      -  (       a  M'  X41mUU4S jn [        R
                  " XXES9nX4U4v   MO     g! [        R                   a    X4[        S5      4v    Mx  f = f7f)a  Iterate over local bridges of `G` optionally computing the span

A *local bridge* is an edge whose endpoints have no common neighbors.
That is, the edge is not part of a triangle in the graph.

The *span* of a *local bridge* is the shortest path length between
the endpoints if the local bridge is removed.

Parameters
----------
G : undirected graph

with_span : bool
    If True, yield a 3-tuple `(u, v, span)`

weight : function, string or None (default: None)
    If function, used to compute edge weights for the span.
    If string, the edge data attribute used in calculating span.
    If None, all edges have weight 1.

Yields
------
e : edge
    The local bridges as an edge 2-tuple of nodes `(u, v)` or
    as a 3-tuple `(u, v, span)` when `with_span is True`.

Raises
------
NetworkXNotImplemented
    If `G` is a directed graph or multigraph.

Examples
--------
A cycle graph has every edge a local bridge with span N-1.

   >>> G = nx.cycle_graph(9)
   >>> (0, 8, 8) in set(nx.local_bridges(G))
   True
Tc                 0   > U T;  d  UT;  a	  T" XU5      $ g N )nnbrdenodeswts      r   	hide_edge local_bridges.<locals>.hide_edge   s     #V*;!!!},    )r#   infN)r   r   r   weighted_weight_functionshortest_path_lengthNetworkXNoPathfloat)	r   	with_spanr#   r   r   r.   spanr,   r-   s	          @@r   r   r      s     V GGDAIAD	))d
  [[))!4GGDAIAD	)) 
-221MD*$  (( -e,,-s5   5C.AC.
C.$C?C.#C+'C.*C++C.r'   )TN)__doc__	itertoolsr   networkxr   networkx.utilsr   __all___dispatchabler   r   r   r(   r0   r   <module>r?      s        .
5 Z C  !CL Z 7  !7t \"Z X&;- ' ! #;-r0   