結果
問題 |
No.3206 う し た ウ ニ 木 あ く ん 笑
|
ユーザー |
|
提出日時 | 2025-07-18 22:19:26 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 308 ms / 3,000 ms |
コード長 | 26,985 bytes |
コンパイル時間 | 262 ms |
コンパイル使用メモリ | 82,228 KB |
実行使用メモリ | 105,776 KB |
最終ジャッジ日時 | 2025-07-18 22:19:33 |
合計ジャッジ時間 | 6,814 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 30 |
ソースコード
''' (H) (F) (RCA₈) C ┏━━━━┿━━━━┓ A₇B₇A₆B₆A₅B₅A₄B₄A₃B₃A₂B₂A₁B₁A₀B₀ A B B╂─┲━┓└┏━┓ ┃ ┏┿━┿━┿━┿━┿━┿━┿━┿━┿━┿━┿━┿━┿━┿━┿━┿┓ ┏┿━┿┓ ┃ ┃H┠┐┃H┠─╂S ┃┢━┪ ┢━┪ ┢━┪ ┢━┪ ┢━┪ ┢━┪ ┢━┪ ┢━┪┃ ┃├⊕┤┃ A╂─┺┯┛└┗┯┛ ┃ C₈╂┃F┠─┨F┠─┨F┠─┨F┠─┨F┠─┨F┠─┨F┠─┨F┠╂C₀ C╂∧│┘┃ ┃ └─∨─┘ ┃ ┃┗┯┛ ┗┯┛ ┗┯┛ ┗┯┛ ┗┯┛ ┗┯┛ ┗┯┛ ┗┯┛┃ ┗━┿━┛ ┗━━━━┿━━━━┛ ┗━┿━━━┿━━━┿━━━┿━━━┿━━━┿━━━┿━━━┿━┛ S C' S₇ S₆ S₅ S₄ S₃ S₂ S₁ S₀ ╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸ Submitted by: kobejean ''' def main(): N = read(int) T = read(Tree[N]) D = [0]*len(T.Ua) I = T.La[:] def edge(s,i,p,u): s += 1 D[I[p]] = s I[p] += 1 return s T.rerooting_dp(0, max2, edge) ans = 0 for u in range(N): P = sorted(D[T.La[u]:I[u]]) n = len(P) for cnt, d in enumerate(P): ans = max2(ans, 1+(n-cnt)*d) write(ans) ''' ╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸ https://kobejean.github.io/cp-library ''' def max2(a, b): return a if a > b else b from typing import Generic, TypeVar _S = TypeVar('S') _T = TypeVar('T') _U = TypeVar('U') import sys def list_find(lst: list, value, start = 0, stop = sys.maxsize): try: return lst.index(value, start, stop) except: return -1 class view(Generic[_T]): __slots__ = 'A', 'l', 'r' def __init__(V, A: list[_T], l: int, r: int): V.A, V.l, V.r = A, l, r def __len__(V): return V.r - V.l def __getitem__(V, i: int): if 0 <= i < V.r - V.l: return V.A[V.l+i] else: raise IndexError def __setitem__(V, i: int, v: _T): V.A[V.l+i] = v def __contains__(V, v: _T): return list_find(V.A, v, V.l, V.r) != -1 def set_range(V, l: int, r: int): V.l, V.r = l, r def index(V, v: _T): return V.A.index(v, V.l, V.r) - V.l def reverse(V): l, r = V.l, V.r-1 while l < r: V.A[l], V.A[r] = V.A[r], V.A[l]; l += 1; r -= 1 def sort(V, /, *args, **kwargs): A = V.A[V.l:V.r]; A.sort(*args, **kwargs) for i,a in enumerate(A,V.l): V.A[i] = a def pop(V): V.r -= 1; return V.A[V.r] def append(V, v: _T): V.A[V.r] = v; V.r += 1 def popleft(V): V.l += 1; return V.A[V.l-1] def appendleft(V, v: _T): V.l -= 1; V.A[V.l] = v; def validate(V): return 0 <= V.l <= V.r <= len(V.A) import os import typing from collections import deque from io import BytesIO, IOBase from math import inf from numbers import Number from types import GenericAlias from typing import Callable, Collection, Iterator, Sequence, Union, overload class FastIO(IOBase): BUFSIZE = 8192 newlines = 0 def __init__(self, file): self._fd = file.fileno() self.buffer = BytesIO() self.writable = "x" in file.mode or "r" not in file.mode self.write = self.buffer.write if self.writable else None def read(self): BUFSIZE = self.BUFSIZE while True: b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE)) if not b: break ptr = self.buffer.tell() self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr) self.newlines = 0 return self.buffer.read() def readline(self): BUFSIZE = self.BUFSIZE while self.newlines == 0: b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE)) self.newlines = b.count(b"\n") + (not b) ptr = self.buffer.tell() self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr) self.newlines -= 1 return self.buffer.readline() def flush(self): if self.writable: os.write(self._fd, self.buffer.getvalue()) self.buffer.truncate(0), self.buffer.seek(0) class IOWrapper(IOBase): stdin: 'IOWrapper' = None stdout: 'IOWrapper' = None def __init__(self, file): self.buffer = FastIO(file) self.flush = self.buffer.flush self.writable = self.buffer.writable def write(self, s): return self.buffer.write(s.encode("ascii")) def read(self): return self.buffer.read().decode("ascii") def readline(self): return self.buffer.readline().decode("ascii") try: sys.stdin = IOWrapper.stdin = IOWrapper(sys.stdin) sys.stdout = IOWrapper.stdout = IOWrapper(sys.stdout) except: pass class TokenStream(Iterator): stream = IOWrapper.stdin def __init__(self): self.queue = deque() def __next__(self): if not self.queue: self.queue.extend(self._line()) return self.queue.popleft() def wait(self): if not self.queue: self.queue.extend(self._line()) while self.queue: yield def _line(self): return TokenStream.stream.readline().split() def line(self): if self.queue: A = list(self.queue) self.queue.clear() return A return self._line() TokenStream.default = TokenStream() class CharStream(TokenStream): def _line(self): return TokenStream.stream.readline().rstrip() CharStream.default = CharStream() ParseFn = Callable[[TokenStream],_T] class Parser: def __init__(self, spec: Union[type[_T],_T]): self.parse = Parser.compile(spec) def __call__(self, ts: TokenStream) -> _T: return self.parse(ts) @staticmethod def compile_type(cls: type[_T], args = ()) -> _T: if issubclass(cls, Parsable): return cls.compile(*args) elif issubclass(cls, (Number, str)): def parse(ts: TokenStream): return cls(next(ts)) return parse elif issubclass(cls, tuple): return Parser.compile_tuple(cls, args) elif issubclass(cls, Collection): return Parser.compile_collection(cls, args) elif callable(cls): def parse(ts: TokenStream): return cls(next(ts)) return parse else: raise NotImplementedError() @staticmethod def compile(spec: Union[type[_T],_T]=int) -> ParseFn[_T]: if isinstance(spec, (type, GenericAlias)): cls = typing.get_origin(spec) or spec args = typing.get_args(spec) or tuple() return Parser.compile_type(cls, args) elif isinstance(offset := spec, Number): cls = type(spec) def parse(ts: TokenStream): return cls(next(ts)) + offset return parse elif isinstance(args := spec, tuple): return Parser.compile_tuple(type(spec), args) elif isinstance(args := spec, Collection): return Parser.compile_collection(type(spec), args) elif isinstance(fn := spec, Callable): def parse(ts: TokenStream): return fn(next(ts)) return parse else: raise NotImplementedError() @staticmethod def compile_line(cls: _T, spec=int) -> ParseFn[_T]: if spec is int: fn = Parser.compile(spec) def parse(ts: TokenStream): return cls([int(token) for token in ts.line()]) return parse else: fn = Parser.compile(spec) def parse(ts: TokenStream): return cls([fn(ts) for _ in ts.wait()]) return parse @staticmethod def compile_repeat(cls: _T, spec, N) -> ParseFn[_T]: fn = Parser.compile(spec) def parse(ts: TokenStream): return cls([fn(ts) for _ in range(N)]) return parse @staticmethod def compile_children(cls: _T, specs) -> ParseFn[_T]: fns = tuple((Parser.compile(spec) for spec in specs)) def parse(ts: TokenStream): return cls([fn(ts) for fn in fns]) return parse @staticmethod def compile_tuple(cls: type[_T], specs) -> ParseFn[_T]: if isinstance(specs, (tuple,list)) and len(specs) == 2 and specs[1] is ...: return Parser.compile_line(cls, specs[0]) else: return Parser.compile_children(cls, specs) @staticmethod def compile_collection(cls, specs): if not specs or len(specs) == 1 or isinstance(specs, set): return Parser.compile_line(cls, *specs) elif (isinstance(specs, (tuple,list)) and len(specs) == 2 and isinstance(specs[1], int)): return Parser.compile_repeat(cls, specs[0], specs[1]) else: raise NotImplementedError() class Parsable: @classmethod def compile(cls): def parser(ts: TokenStream): return cls(next(ts)) return parser @classmethod def __class_getitem__(cls, item): return GenericAlias(cls, item) def chmin(dp, i, v): if ch:=dp[i]>v:dp[i]=v return ch from enum import IntEnum, IntFlag, auto class DFSFlags(IntFlag): ENTER = auto() DOWN = auto() BACK = auto() CROSS = auto() LEAVE = auto() UP = auto() MAXDEPTH = auto() RETURN_PARENTS = auto() RETURN_DEPTHS = auto() BACKTRACK = auto() CONNECT_ROOTS = auto() # Common combinations ALL_EDGES = DOWN | BACK | CROSS EULER_TOUR = DOWN | UP INTERVAL = ENTER | LEAVE TOPDOWN = DOWN | CONNECT_ROOTS BOTTOMUP = UP | CONNECT_ROOTS RETURN_ALL = RETURN_PARENTS | RETURN_DEPTHS class DFSEvent(IntEnum): ENTER = DFSFlags.ENTER DOWN = DFSFlags.DOWN BACK = DFSFlags.BACK CROSS = DFSFlags.CROSS LEAVE = DFSFlags.LEAVE UP = DFSFlags.UP MAXDEPTH = DFSFlags.MAXDEPTH class GraphBase(Parsable): def __init__(G, N: int, M: int, U: list[int], V: list[int], deg: list[int], La: list[int], Ra: list[int], Ua: list[int], Va: list[int], Ea: list[int], twin: list[int] = None): G.N = N '''The number of vertices.''' G.M = M '''The number of edges.''' G.U = U '''A list of source vertices in the original edge list.''' G.V = V '''A list of destination vertices in the original edge list.''' G.deg = deg '''deg[u] is the out degree of vertex u.''' G.La = La '''La[u] stores the start index of the list of adjacent vertices from u.''' G.Ra = Ra '''Ra[u] stores the stop index of the list of adjacent vertices from u.''' G.Ua = Ua '''Ua[i] = u for La[u] <= i < Ra[u], useful for backtracking.''' G.Va = Va '''Va[i] lists adjacent vertices to u for La[u] <= i < Ra[u].''' G.Ea = Ea '''Ea[i] lists the edge ids that start from u for La[u] <= i < Ra[u]. For undirected graphs, edge ids in range M<= e <2*M are edges from V[e-M] -> U[e-M]. ''' G.twin = twin if twin is not None else range(len(Ua)) '''twin[i] in undirected graphs stores index j of the same edge but with u and v swapped.''' G.st: list[int] = None G.order: list[int] = None G.vis: list[int] = None G.back: list[int] = None G.tin: list[int] = None def clear(G): G.vis = G.back = G.tin = None def prep_vis(G): if G.vis is None: G.vis = u8f(G.N) return G.vis def prep_st(G): if G.st is None: G.st = elist(G.N) else: G.st.clear() return G.st def prep_order(G): if G.order is None: G.order = elist(G.N) else: G.order.clear() return G.order def prep_back(G): if G.back is None: G.back = i32f(G.N, -2) return G.back def prep_tin(G): if G.tin is None: G.tin = i32f(G.N, -1) return G.tin def _remove(G, a: int): G.deg[u := G.Ua[a]] -= 1 G.Ra[u] = (r := G.Ra[u]-1) G.Ua[a], G.Va[a], G.Ea[a] = G.Ua[r], G.Va[r], G.Ea[r] G.twin[a], G.twin[r] = G.twin[r], G.twin[a] G.twin[G.twin[a]] = a G.twin[G.twin[r]] = r def remove(G, a: int): b = G.twin[a]; G._remove(a) if a != b: G._remove(b) def __len__(G) -> int: return G.N def __getitem__(G, u): return view(G.Va, G.La[u], G.Ra[u]) def range(G, u): return range(G.La[u],G.Ra[u]) @overload def distance(G) -> list[list[int]]: ... @overload def distance(G, s: int = 0) -> list[int]: ... @overload def distance(G, s: int, g: int) -> int: ... def distance(G, s = None, g = None): if s == None: return G.floyd_warshall() else: return G.bfs(s, g) def recover_path(G, s, t): Ua, back, vertices = G.Ua, G.back, u32f(1, v := t) while v != s: vertices.append(v := Ua[back[v]]) return vertices def recover_path_edge_ids(G, s, t): Ea, Ua, back, edges, v = G.Ea, G.Ua, G.back, u32f(0), t while v != s: edges.append(Ea[i := back[v]]), (v := Ua[i]) return edges def shortest_path(G, s: int, t: int): if G.distance(s, t) >= inf: return None vertices = G.recover_path(s, t) vertices.reverse() return vertices def shortest_path_edge_ids(G, s: int, t: int): if G.distance(s, t) >= inf: return None edges = G.recover_path_edge_ids(s, t) edges.reverse() return edges @overload def bfs(G, s: Union[int,list] = 0) -> list[int]: ... @overload def bfs(G, s: Union[int,list], g: int) -> int: ... def bfs(G, s: int = 0, g: int = None): S, Va, back, D = G.starts(s), G.Va, i32f(N := G.N, -1), [inf]*N G.back, G.D = back, D for u in S: D[u] = 0 que = deque(S) while que: nd = D[u := que.popleft()]+1 if u == g: return nd-1 for i in G.range(u): if nd < D[v := Va[i]]: D[v], back[v] = nd, i que.append(v) return D if g is None else inf def floyd_warshall(G) -> list[list[int]]: G.D = D = [[inf]*G.N for _ in range(G.N)] for u in range(G.N): D[u][u] = 0 for i in range(len(G.Ua)): D[G.Ua[i]][G.Va[i]] = 1 for k, Dk in enumerate(D): for Di in D: if (Dik := Di[k]) == inf: continue for j in range(G.N): chmin(Di, j, Dik+Dk[j]) return D def find_cycle_indices(G, s: Union[int, None] = None): Ea, Ua, Va, vis, back = G.Ea, G. Ua, G.Va, u8f(N := G.N), u32f(N, i32_max) G.vis, G.back, st = vis, back, elist(N) for s in G.starts(s): if vis[s]: continue st.append(s) while st: if not vis[u := st.pop()]: st.append(u) vis[u], pe = 1, Ea[j] if (j := back[u]) != i32_max else i32_max for i in G.range(u): if not vis[v := Va[i]]: back[v] = i st.append(v) elif vis[v] == 1 and pe != Ea[i]: I = u32f(1,i) while v != u: I.append(i := back[u]), (u := Ua[i]) I.reverse() return I else: vis[u] = 2 # check for self loops for i in range(len(Ua)): if Ua[i] == Va[i]: return u32f(1,i) def find_cycle(G, s: Union[int, None] = None): if I := G.find_cycle_indices(s): return [G.Ua[i] for i in I] def find_cycle_edge_ids(G, s: Union[int, None] = None): if I := G.find_cycle_indices(s): return [G.Ea[i] for i in I] def find_minimal_cycle(G, s=0): D, par, que, Va = u32f(N := G.N, u32_max), i32f(N, -1), deque([s]), G.Va D[s] = 0 while que: for i in G.range(u := que.popleft()): if (v := Va[i]) == s: # Found cycle back to start cycle = [u] while u != s: cycle.append(u := par[u]) return cycle if D[v] < u32_max: continue D[v], par[v] = D[u]+1, u; que.append(v) def dfs_topdown(G, s: Union[int,list] = None) -> list[int]: '''Returns lists of indices i where Ua[i] -> Va[i] are edges in order of top down discovery''' vis, st, order = G.prep_vis(), G.prep_st(), G.prep_order() for s in G.starts(s): if vis[s]: continue vis[s] = 1; st.append(s) while st: for i in G.range(st.pop()): if vis[v := G.Va[i]]: continue vis[v] = 1; order.append(i); st.append(v) return order def dfs(G, s: Union[int,list] = None, /, backtrack = False, max_depth = None, enter_fn: Callable[[int],None] = None, leave_fn: Callable[[int],None] = None, max_depth_fn: Callable[[int],None] = None, down_fn: Callable[[int,int,int],None] = None, back_fn: Callable[[int,int,int],None] = None, forward_fn: Callable[[int,int,int],None] = None, cross_fn: Callable[[int,int,int],None] = None, up_fn: Callable[[int,int,int],None] = None): I, time, vis, st, back, tin = G.La[:], -1, G.prep_vis(), G.prep_st(), G.prep_back(), G.prep_tin() for s in G.starts(s): if vis[s]: continue back[s], tin[s] = -1, (time := time+1); st.append(s) while st: if vis[u := st[-1]] == 0: vis[u] = 1 if enter_fn: enter_fn(u) if max_depth is not None and len(st) > max_depth: I[u] = G.Ra[u] if max_depth_fn: max_depth_fn(u) if (i := I[u]) < G.Ra[u]: I[u] += 1 if (s := vis[v := G.Va[i]]) == 0: back[v], tin[v] = i, (time := time+1); st.append(v) if down_fn: down_fn(u,v,i) elif back_fn and s == 1 and back[u] != G.twin[i]: back_fn(u,v,i) elif (cross_fn or forward_fn) and s == 2: if forward_fn and tin[u] < tin[v]: forward_fn(u,v,i) elif cross_fn: cross_fn(u,v,i) else: vis[u] = 2; st.pop() if backtrack: vis[u], I[u] = 0, G.La[u] if leave_fn: leave_fn(u) if up_fn and st: up_fn(u, st[-1], back[u]) def dfs_enter_leave(G, s: Union[int,list[int],None] = None) -> Sequence[tuple[DFSEvent,int]]: N, I = G.N, G.La[:] st, back, plst = elist(N), i32f(N,-2), PacketList(order := elist(2*N), N-1) G.back, ENTER, LEAVE = back, int(DFSEvent.ENTER) << plst.shift, int(DFSEvent.LEAVE) << plst.shift for s in G.starts(s): if back[s] >= -1: continue back[s] = -1 order.append(ENTER | s), st.append(s) while st: if (i := I[u := st[-1]]) < G.Ra[u]: I[u] += 1 if back[v := G.Va[i]] >= -1: continue back[v] = i; order.append(ENTER | v); st.append(v) else: order.append(LEAVE | u); st.pop() return plst def starts(G, s: Union[int,list[int],None] = None) -> list[int]: if isinstance(s, int): return [s] elif s is None: return range(G.N) elif isinstance(s, list): return s else: return list(s) @classmethod def compile(cls, N: int, M: int, shift: int = -1): def parse(ts: TokenStream): U, V = u32f(M), u32f(M) for i in range(M): u, v = ts._line() U[i], V[i] = int(u)+shift, int(v)+shift return cls(N, U, V) return parse u32_max = (1<<32)-1 i32_max = (1<<31)-1 from array import array def u8f(N: int, elm: int = 0): return array('B', (elm,))*N # unsigned char def u32f(N: int, elm: int = 0): return array('I', (elm,))*N # unsigned int def i32f(N: int, elm: int = 0): return array('i', (elm,))*N # signed int def elist(est_len: int) -> list: ... try: from __pypy__ import newlist_hint except: def newlist_hint(hint): return [] elist = newlist_hint class PacketList(Sequence[tuple[int,int]]): def __init__(lst, A: list[int], max1: int): lst.A = A lst.mask = (1 << (shift := (max1).bit_length())) - 1 lst.shift = shift def __len__(lst): return lst.A.__len__() def __contains__(lst, x: tuple[int,int]): return lst.A.__contains__(x[0] << lst.shift | x[1]) def __getitem__(lst, key) -> tuple[int,int]: x = lst.A[key] return x >> lst.shift, x & lst.mask class Graph(GraphBase): def __init__(G, N: int, U: list[int], V: list[int]): M, Ma, deg = len(U), 0, u32f(N) for e in range(M := len(U)): distinct = (u := U[e]) != (v := V[e]) deg[u] += 1; deg[v] += distinct; Ma += 1+distinct twin, Ea, Ua, Va, La, Ra, i = i32f(Ma), i32f(Ma), u32f(Ma), u32f(Ma), u32f(N), u32f(N), 0 for u in range(N): La[u] = Ra[u] = i; i = i+deg[u] for e in range(M): i, j = Ra[u := U[e]], Ra[v := V[e]] Ra[u], Ua[i], Va[i], Ea[i], twin[i] = i+1, u, v, e, j if i == j: continue Ra[v], Ua[j], Va[j], Ea[j], twin[j] = j+1, v, u, e, i super().__init__(N, M, U, V, deg, La, Ra, Ua, Va, Ea, twin) from typing import Callable, Literal, Union, overload class TreeBase(GraphBase): @overload def distance(T) -> list[list[int]]: ... @overload def distance(T, s: int = 0) -> list[int]: ... @overload def distance(T, s: int, g: int) -> int: ... def distance(T, s = None, g = None): if s == None: return [T.dfs_distance(u) for u in range(T.N)] else: return T.dfs_distance(s, g) @overload def diameter(T) -> int: ... @overload def diameter(T, endpoints: Literal[True]) -> tuple[int,int,int]: ... def diameter(T, endpoints = False): mask = (1 << (shift := T.N.bit_length())) - 1 s = max(d << shift | v for v,d in enumerate(T.distance(0))) & mask dg = max(d << shift | v for v,d in enumerate(T.distance(s))) diam, g = dg >> shift, dg & mask return (diam, s, g) if endpoints else diam def dfs_distance(T, s: int, g: Union[int,None] = None): st, Va = elist(N := T.N), T.Va T.D, T.back = D, back = [inf]*N, i32f(N, -1) D[s] = 0 st.append(s) while st: nd = D[u := st.pop()]+1 if u == g: return nd-1 for i in T.range(u): if nd < D[v := Va[i]]: D[v], back[v] = nd, i st.append(v) return D if g is None else inf def rerooting_dp(T, e: _T, merge: Callable[[_T,_T],_T], edge_op: Callable[[_T,int,int,int],_T] = lambda s,i,p,u:s, s: int = 0): La, Ua, Va = T.La, T.Ua, T.Va order, dp, suf, I = T.dfs_topdown(s), [e]*T.N, [e]*len(Ua), T.Ra[:] # up for i in order[::-1]: u,v = Ua[i], Va[i] # subtree v finished up pass, store value to accumulate for u dp[v] = new = edge_op(dp[v], i, u, v) dp[u] = merge(dp[u], new) # suffix accumulation if (c:=I[u]-1) > La[u]: suf[c-1] = merge(suf[c], new) I[u] = c # down dp[s] = e # at this point dp stores values to be merged in parent for i in order: u,v = Ua[i], Va[i] dp[u] = merge(pre := dp[u], dp[v]) dp[v] = edge_op(merge(suf[I[u]], pre), i, v, u) I[u] += 1 return dp def euler_tour(T, s = 0): N, Va = len(T), T.Va tin, tout, par, back = [-1]*N,[-1]*N,[-1]*N,[0]*N order, delta = elist(2*N), elist(2*N) st = elist(N); st.append(s) while st: p = par[u := st.pop()] if tin[u] == -1: tin[u] = len(order) for i in T.range(u): if (v := Va[i]) != p: par[v], back[v] = u, i st.append(u); st.append(v) delta.append(1) else: delta.append(-1) order.append(u) tout[u] = len(order) delta[0] = delta[-1] = 0 T.tin, T.tout, T.par, T.back = tin, tout, par, back T.order, T.delta = order, delta @classmethod def compile(cls, N: int, shift: int = -1): return GraphBase.compile.__func__(cls, N, N-1, shift) class Tree(TreeBase, Graph): pass from typing import Type, Union, overload @overload def read() -> list[int]: ... @overload def read(spec: Type[_T], char=False) -> _T: ... @overload def read(spec: _U, char=False) -> _U: ... @overload def read(*specs: Type[_T], char=False) -> tuple[_T, ...]: ... @overload def read(*specs: _U, char=False) -> tuple[_U, ...]: ... def read(*specs: Union[Type[_T],_U], char=False): if not char and not specs: return [int(s) for s in TokenStream.default.line()] parser: _T = Parser.compile(specs[0] if len(specs) == 1 else specs) return parser(CharStream.default if char else TokenStream.default) def write(*args, **kwargs): '''Prints the values to a stream, or to stdout_fast by default.''' sep, file = kwargs.pop("sep", " "), kwargs.pop("file", IOWrapper.stdout) at_start = True for x in args: if not at_start: file.write(sep) file.write(str(x)) at_start = False file.write(kwargs.pop("end", "\n")) if kwargs.pop("flush", False): file.flush() def debug(*args, **kwargs): if debug.on: kwargs.setdefault('file', sys.stderr) print(*args, **kwargs) debug.on = False debug.on = True if __name__ == "__main__": main()