from collections.abc import Callable
from typing import Any

class UnionFind:
    def __init__(self, n: int) -> None: ...
    def find(self, i: int) -> int: ...
    def union(self, i: int, j: int) -> bool: ...
    def equiv(self, i: int, j: int) -> bool: ...
    def into_labeling(self) -> list[int]: ...
    def __repr__(self) -> str: ...
    def __len__(self) -> int: ...

class DiGraph:
    def __init__(self, nodes: int = 0, edges: int = 0) -> None: ...
    @staticmethod
    def from_edges(
        edges: list[tuple[int, int, Any]], node_count: int | None = None
    ) -> DiGraph: ...
    def add_node(self, weight: Any) -> int: ...
    def remove_node(self, index: int) -> Any | None: ...
    def add_edge(self, u: int, v: int, weight: Any) -> int: ...
    def update_edge(self, u: int, v: int, weight: Any) -> int: ...
    def remove_edge(self, index: int) -> Any | None: ...
    def clear(self) -> None: ...
    def clear_edges(self) -> None: ...
    def reverse(self) -> None: ...
    @property
    def node_count(self) -> int: ...
    @property
    def edge_count(self) -> int: ...
    @property
    def is_directed(self) -> bool: ...
    def node_weight(self, index: int) -> Any | None: ...
    def edge_weight(self, index: int) -> Any | None: ...
    def find_edge(self, u: int, v: int) -> int | None: ...
    def neighbors(self, index: int) -> list[int]: ...
    def out_degree(self, index: int) -> int: ...
    def in_degree(self, index: int) -> int: ...
    def node_indices(self) -> list[int]: ...
    def edge_indices(self) -> list[int]: ...
    def bfs(self, start: int) -> list[int]: ...
    def dfs(self, start: int) -> list[int]: ...
    def is_cyclic(self) -> bool: ...
    async def is_cyclic_async(self) -> bool: ...
    def toposort(self) -> list[int]: ...
    async def toposort_async(self) -> list[int]: ...
    def dijkstra(self, start: int) -> dict[int, float]: ...
    async def dijkstra_async(self, start: int) -> dict[int, float]: ...
    def floyd_warshall(self) -> dict[int, dict[int, float]]: ...
    async def floyd_warshall_async(self) -> dict[int, dict[int, float]]: ...
    def k_shortest_path(
        self,
        start: int,
        goal: int,
        k: int,
        weight_fn: Callable[[int, int, Any], float] | None = None,
    ) -> dict[int, float]: ...
    async def k_shortest_path_async(
        self,
        start: int,
        goal: int,
        k: int,
        weight_fn: Callable[[int, int, Any], float] | None = None,
    ) -> dict[int, float]: ...
    def astar(
        self, start: int, goal: int, heuristic_fn: Any
    ) -> tuple[float, list[int]] | None: ...
    async def astar_async(
        self, start: int, goal: int, heuristic_fn: Any
    ) -> tuple[float, list[int]] | None: ...
    def tarjan_scc(self) -> list[list[int]]: ...
    async def tarjan_scc_async(self) -> list[list[int]]: ...
    def kosaraju_scc(self) -> list[list[int]]: ...
    async def kosaraju_scc_async(self) -> list[list[int]]: ...
    def all_simple_paths(
        self,
        from_node: int,
        to_node: int,
        min_intermediate_nodes: int = 0,
        max_intermediate_nodes: int | None = None,
    ) -> list[list[int]]: ...
    async def all_simple_paths_async(
        self,
        from_node: int,
        to_node: int,
        min_intermediate_nodes: int = 0,
        max_intermediate_nodes: int | None = None,
    ) -> list[list[int]]: ...
    def has_path_connecting(self, from_node: int, to_node: int) -> bool: ...
    async def has_path_connecting_async(
        self, from_node: int, to_node: int
    ) -> bool: ...
    def page_rank(
        self, damping_factor: float = 0.85, iterations: int = 100, tol: float = 1e-6
    ) -> list[float]: ...
    async def page_rank_async(
        self, damping_factor: float = 0.85, iterations: int = 100, tol: float = 1e-6
    ) -> list[float]: ...
    def to_scipy_coo(self) -> tuple[list[int], list[int], list[float]]: ...
    def to_dot(self) -> str: ...
    def __repr__(self) -> str: ...
    def __len__(self) -> int: ...
    def __bool__(self) -> bool: ...
    def __contains__(self, index: int) -> bool: ...

class UnGraph:
    def __init__(self, nodes: int = 0, edges: int = 0) -> None: ...
    def add_node(self, weight: Any) -> int: ...
    def remove_node(self, index: int) -> Any | None: ...
    def add_edge(self, u: int, v: int, weight: Any) -> int: ...
    @property
    def node_count(self) -> int: ...
    @property
    def edge_count(self) -> int: ...
    @property
    def is_directed(self) -> bool: ...
    def degree(self, index: int) -> int: ...
    def clear(self) -> None: ...
    def connected_components(self) -> int: ...
    async def connected_components_async(self) -> int: ...
    def bfs(self, start: int) -> list[int]: ...
    def dfs(self, start: int) -> list[int]: ...
    def has_path_connecting(self, from_node: int, to_node: int) -> bool: ...
    async def has_path_connecting_async(
        self, from_node: int, to_node: int
    ) -> bool: ...
    def is_bipartite(self, start: int) -> bool: ...
    async def is_bipartite_async(self, start: int) -> bool: ...
    def to_dot(self) -> str: ...
    def __repr__(self) -> str: ...
    def __len__(self) -> int: ...
    def __bool__(self) -> bool: ...

class FastDiGraph:
    def __init__(self, nodes: int = 0, edges: int = 0) -> None: ...
    def add_node(self, weight: Any) -> int: ...
    def add_edge(self, u: int, v: int, weight: float) -> int: ...
    @property
    def node_count(self) -> int: ...
    @property
    def edge_count(self) -> int: ...
    def node_weight(self, index: int) -> Any | None: ...
    def dijkstra(self, start: int) -> dict[int, float]: ...
    async def dijkstra_async(self, start: int) -> dict[int, float]: ...
    def bellman_ford(self, start: int) -> dict[int, float]: ...
    async def bellman_ford_async(self, start: int) -> dict[int, float]: ...
    def floyd_warshall(self) -> dict[int, dict[int, float]]: ...
    async def floyd_warshall_async(self) -> dict[int, dict[int, float]]: ...
    def astar(
        self, start: int, goal: int, heuristic_fn: Any
    ) -> tuple[float, list[int]] | None: ...
    async def astar_async(
        self, start: int, goal: int, heuristic_fn: Any
    ) -> tuple[float, list[int]] | None: ...
    def is_cyclic(self) -> bool: ...
    async def is_cyclic_async(self) -> bool: ...
    def toposort(self) -> list[int]: ...
    async def toposort_async(self) -> list[int]: ...
    def tarjan_scc(self) -> list[list[int]]: ...
    async def tarjan_scc_async(self) -> list[list[int]]: ...
    def has_path_connecting(self, from_node: int, to_node: int) -> bool: ...
    async def has_path_connecting_async(
        self, from_node: int, to_node: int
    ) -> bool: ...
    def page_rank(
        self, damping_factor: float = 0.85, iterations: int = 100, tol: float = 1e-6
    ) -> list[float]: ...
    async def page_rank_async(
        self, damping_factor: float = 0.85, iterations: int = 100, tol: float = 1e-6
    ) -> list[float]: ...
    def to_scipy_coo(self) -> tuple[list[int], list[int], list[float]]: ...
    def bfs(self, start: int) -> list[int]: ...
    def dfs(self, start: int) -> list[int]: ...
    def all_simple_paths(
        self,
        from_node: int,
        to_node: int,
        min_intermediate_nodes: int = 0,
        max_intermediate_nodes: int | None = None,
    ) -> list[list[int]]: ...
    async def all_simple_paths_async(
        self,
        from_node: int,
        to_node: int,
        min_intermediate_nodes: int = 0,
        max_intermediate_nodes: int | None = None,
    ) -> list[list[int]]: ...
    def to_dot(self) -> str: ...
    def __repr__(self) -> str: ...
    def __len__(self) -> int: ...
    def __bool__(self) -> bool: ...

class StableDiGraph:
    def __init__(self) -> None: ...
    def add_node(self, weight: Any) -> int: ...
    def remove_node(self, index: int) -> Any | None: ...
    def add_edge(self, u: int, v: int, weight: Any) -> int: ...
    def remove_edge(self, index: int) -> Any | None: ...
    def contains_node(self, index: int) -> bool: ...
    @property
    def node_count(self) -> int: ...
    @property
    def edge_count(self) -> int: ...
    def __repr__(self) -> str: ...
    def __len__(self) -> int: ...
    def __bool__(self) -> bool: ...
    def __contains__(self, index: int) -> bool: ...

class IntGraphMap:
    def __init__(self) -> None: ...
    def add_node(self, node: int) -> None: ...
    def remove_node(self, node: int) -> bool: ...
    def add_edge(self, u: int, v: int, weight: Any) -> None: ...
    def remove_edge(self, u: int, v: int) -> Any | None: ...
    def contains_node(self, node: int) -> bool: ...
    def contains_edge(self, u: int, v: int) -> bool: ...
    @property
    def node_count(self) -> int: ...
    @property
    def edge_count(self) -> int: ...
    def neighbors(self, node: int) -> list[int]: ...
    def all_nodes(self) -> list[int]: ...
    def all_edges(self) -> list[tuple[int, int, Any]]: ...
    def degree(self, node: int) -> int: ...
    def __repr__(self) -> str: ...
    def __len__(self) -> int: ...
    def __bool__(self) -> bool: ...

class IntDiGraphMap:
    def __init__(self) -> None: ...
    def add_node(self, node: int) -> None: ...
    def remove_node(self, node: int) -> bool: ...
    def add_edge(self, u: int, v: int, weight: Any) -> None: ...
    def remove_edge(self, u: int, v: int) -> Any | None: ...
    @property
    def node_count(self) -> int: ...
    @property
    def edge_count(self) -> int: ...
    def neighbors(self, node: int) -> list[int]: ...
    def out_degree(self, node: int) -> int: ...
    def in_degree(self, node: int) -> int: ...
    def dijkstra(self, start: int) -> dict[int, float]: ...
    def __repr__(self) -> str: ...
    def __len__(self) -> int: ...
    def __bool__(self) -> bool: ...

class MatrixDiGraph:
    def __init__(self) -> None: ...
    def add_node(self, weight: Any) -> int: ...
    def add_edge(self, u: int, v: int, weight: float) -> None: ...
    def has_edge(self, u: int, v: int) -> bool: ...
    def remove_edge(self, u: int, v: int) -> bool: ...
    @property
    def node_count(self) -> int: ...
    @property
    def edge_count(self) -> int: ...
    def dijkstra(self, start: int) -> dict[int, float]: ...
    async def dijkstra_async(self, start: int) -> dict[int, float]: ...
    def bellman_ford(self, start: int) -> dict[int, float]: ...
    async def bellman_ford_async(self, start: int) -> dict[int, float]: ...
    def __repr__(self) -> str: ...
    def __len__(self) -> int: ...
    def __bool__(self) -> bool: ...

class CsrGraph:
    @staticmethod
    def from_edges(
        node_count: int,
        edges: list[tuple[int, int, float]],
        sorted: bool = False,
    ) -> CsrGraph: ...
    @property
    def node_count(self) -> int: ...
    @property
    def edge_count(self) -> int: ...
    def dijkstra(self, start: int) -> dict[int, float]: ...
    async def dijkstra_async(self, start: int) -> dict[int, float]: ...
    def bellman_ford(self, start: int) -> dict[int, float]: ...
    async def bellman_ford_async(self, start: int) -> dict[int, float]: ...
    def floyd_warshall(self) -> dict[int, dict[int, float]]: ...
    async def floyd_warshall_async(self) -> dict[int, dict[int, float]]: ...
    def __repr__(self) -> str: ...
    def __len__(self) -> int: ...
    def __bool__(self) -> bool: ...

def is_isomorphic(g1: DiGraph, g2: DiGraph) -> bool: ...
async def is_isomorphic_async(g1: DiGraph, g2: DiGraph) -> bool: ...
