
from __future__ import annotations

from typing import Generic, TypeVar

lowercase_ 				=			TypeVar("""T""")





class     __UpperCamelCase (							Generic[T]       ):






     """simple docstring"""







     def __init__(				self							:							Optional[int]     ,						_A							:							T ):







       """simple docstring"""




       __SCREAMING_SNAKE_CASE      :	List[str]					=		data
       __SCREAMING_SNAKE_CASE      :	Optional[Any]					=		self
       __SCREAMING_SNAKE_CASE      :	Optional[int]					=		0






class     __UpperCamelCase (							Generic[T]       ):






     """simple docstring"""







     def __init__(				self							:							Optional[Any] ):







       """simple docstring"""




       __SCREAMING_SNAKE_CASE      :	dict[T, DisjointSetTreeNode[T]]					=		{}



     def  UpperCAmelCase__							(				self							:							Dict     ,						_A							:							T ):







       """simple docstring"""




       __SCREAMING_SNAKE_CASE      :	Dict					=		DisjointSetTreeNode(_A )



     def  UpperCAmelCase__							(				self							:							Optional[Any]     ,						_A							:							T ):







       """simple docstring"""




       __SCREAMING_SNAKE_CASE      :	Union[str, Any]					=		self.map[data]
       if elem_ref != elem_ref.parent:
         __SCREAMING_SNAKE_CASE      :	Optional[Any]					=		self.find_set(elem_ref.parent.data )
       return elem_ref.parent



     def  UpperCAmelCase__							(				self							:							Optional[Any]     ,						_A							:							DisjointSetTreeNode[T]     ,						_A							:							DisjointSetTreeNode[T] ):







       """simple docstring"""




       if nodea.rank > nodea.rank:
         __SCREAMING_SNAKE_CASE      :	Union[str, Any]					=		nodea
       else:
         __SCREAMING_SNAKE_CASE      :	Union[str, Any]					=		nodea
         if nodea.rank == nodea.rank:
           nodea.rank += 1




     def  UpperCAmelCase__							(				self							:							str     ,						_A							:							T     ,						_A							:							T ):







       """simple docstring"""




       self.link(self.find_set(_A )     ,						self.find_set(_A ) )






class     __UpperCamelCase (							Generic[T]       ):






     """simple docstring"""







     def __init__(				self							:							List[Any] ):







       """simple docstring"""




       __SCREAMING_SNAKE_CASE      :	dict[T, dict[T, int]]					=		{}



     def  UpperCAmelCase__							(				self							:							int     ,						_A							:							T ):







       """simple docstring"""




       if node not in self.connections:
         __SCREAMING_SNAKE_CASE      :	Tuple					=		{}



     def  UpperCAmelCase__							(				self							:							Optional[int]     ,						_A							:							T     ,						_A							:							T     ,						_A							:							int ):







       """simple docstring"""




       self.add_node(_A )
       self.add_node(_A )
       __SCREAMING_SNAKE_CASE      :	Tuple					=		weight
       __SCREAMING_SNAKE_CASE      :	Union[str, Any]					=		weight




     def  UpperCAmelCase__							(				self							:							Dict ):







       """simple docstring"""




       __SCREAMING_SNAKE_CASE      :	List[str]					=		[]
       __SCREAMING_SNAKE_CASE      :	List[Any]					=		set()
       for start in self.connections:
         for end in self.connections[start]:
           if (start, end) not in seen:
             seen.add((end, start) )
             edges.append((start, end, self.connections[start][end]) )
       edges.sort(key=lambda _A : x[2] )

       # creating the disjoint set
       __SCREAMING_SNAKE_CASE      :	Tuple					=		DisjointSetTree[T]()
       for node in self.connections:
         disjoint_set.make_set(_A )

       # MST generation
       __SCREAMING_SNAKE_CASE      :	Optional[Any]					=		0
       __SCREAMING_SNAKE_CASE      :	Optional[Any]					=		0
       __SCREAMING_SNAKE_CASE      :	List[str]					=		GraphUndirectedWeighted[T]()
       while num_edges < len(self.connections ) - 1:
         __SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE      :	List[str]					=		edges[index]
         index += 1
         __SCREAMING_SNAKE_CASE      :	Dict					=		disjoint_set.find_set(_A )
         __SCREAMING_SNAKE_CASE      :	Optional[Any]					=		disjoint_set.find_set(_A )
         if parent_u != parent_v:
           num_edges += 1
           graph.add_edge(_A     ,						_A     ,						_A )
           disjoint_set.union(_A     ,						_A )
       return graph


from __future__ import annotations




def 	UpperCamelCase__  (     SCREAMING_SNAKE_CASE_	:	float		,   SCREAMING_SNAKE_CASE_	:	float		,   SCREAMING_SNAKE_CASE_	:	float		,   )  ->     tuple:
						if (electron_conc, hole_conc, intrinsic_conc).count(0       ) != 1:
												raise ValueError("""You cannot supply more or less than 2 values"""       )
						elif electron_conc < 0:
												raise ValueError("""Electron concentration cannot be negative in a semiconductor"""       )
						elif hole_conc < 0:
												raise ValueError("""Hole concentration cannot be negative in a semiconductor"""       )
						elif intrinsic_conc < 0:
												raise ValueError(
												    """Intrinsic concentration cannot be negative in a semiconductor"""       )
						elif electron_conc == 0:
												return (
												    "electron_conc",
												    intrinsic_conc**2 / hole_conc,
												)
						elif hole_conc == 0:
												return (
												    "hole_conc",
												    intrinsic_conc**2 / electron_conc,
												)
						elif intrinsic_conc == 0:
												return (
												    "intrinsic_conc",
												    (electron_conc * hole_conc) ** 0.5,
												)
						else:
												return (-1, -1)


if __name__ == "__main__":
		import doctest

		doctest.testmod()