#pragma once
#include"library/graph/Graph.hpp"
#include"library/graph/ReverseGraph.hpp"
#define REP_(i, n) for (int i = 0; i < (n); i++)
template<typenameDirectedGraph>classSCC{intn;DirectedGraphG,R;std::vector<int>visit,belong;std::vector<uint8_t>used;voiddfs(intv){used[v]=true;for(intto:G[v])if(!used[to])dfs(to);visit.push_back(v);}voidrdfs(intv,intk){used[v]=true;belong[v]=k;for(intto:R[v])if(!used[to])rdfs(to,k);}public:GraphDAG;std::vector<std::vector<int>>component;SCC(constDirectedGraph&G):n(G.n),G(G),belong(n),used(n,false){assert(G.is_prepared());visit.reserve(n);R=reverse_graph(G);REP_(v,n)if(!used[v])dfs(v);std::ranges::fill(used,false);std::ranges::reverse(visit);intk=0;for(constint&v:visit)if(!used[v])rdfs(v,k++);std::vector<std::vector<int>>edges(k);component.resize(k);REP_(v,n){component[belong[v]].push_back(v);for(intto:G[v])if(belong[v]!=belong[to])edges[belong[v]].push_back(belong[to]);}DAG=Graph(k);REP_(from,k){std::ranges::sort(edges[from]);REP_(i,edges[from].size())if(!i||edges[from][i]!=edges[from][i-1])DAG.add_arc(from,edges[from][i]);}}intoperator[](intk){returnbelong[k];}};#undef REP_
#line 2 "library/graph/Graph.hpp"
#include<cassert>
#include<iostream>
#include<vector>structEdge{intfrom,to;Edge()=default;Edge(intfrom,intto):from(from),to(to){}operatorint()const{returnto;}};structGraph{intn;usingedge_type=Edge;std::vector<edge_type>edges;protected:std::vector<int>in_deg;boolprepared;classOutgoingEdges{Graph*g;intl,r;public:OutgoingEdges(Graph*g,intl,intr):g(g),l(l),r(r){}edge_type*begin(){return&(g->edges[l]);}edge_type*end(){return&(g->edges[r]);}edge_type&operator[](inti){returng->edges[l+i];}intsize()const{returnr-l;}};classConstOutgoingEdges{constGraph*g;intl,r;public:ConstOutgoingEdges(constGraph*g,intl,intr):g(g),l(l),r(r){}constedge_type*begin()const{return&(g->edges[l]);}constedge_type*end()const{return&(g->edges[r]);}constedge_type&operator[](inti)const{returng->edges[l+i];}intsize()const{returnr-l;}};public:OutgoingEdgesoperator[](intv){assert(prepared);return{this,in_deg[v],in_deg[v+1]};}constConstOutgoingEdgesoperator[](intv)const{assert(prepared);return{this,in_deg[v],in_deg[v+1]};}boolis_prepared()const{returnprepared;}Graph():n(0),in_deg(1,0),prepared(false){}Graph(intn):n(n),in_deg(n+1,0),prepared(false){}Graph(intn,intm,booldirected=false,intindexed=1):n(n),in_deg(n+1,0),prepared(false){scan(m,directed,indexed);}voidresize(intn){n=n;}voidadd_arc(intfrom,intto){assert(!prepared);assert(0<=fromandfrom<nand0<=toandto<n);edges.emplace_back(from,to);in_deg[from+1]++;}voidadd_edge(intu,intv){add_arc(u,v);add_arc(v,u);}voidadd_arc(constedge_type&e){add_arc(e.from,e.to);}voidadd_edge(constedge_type&e){add_edge(e.from,e.to);}voidscan(intm,booldirected=false,intindexed=1){edges.reserve(directed?m:2*m);while(m--){intu,v;std::cin>>u>>v;u-=indexed;v-=indexed;if(directed)add_arc(u,v);elseadd_edge(u,v);}build();}voidbuild(){assert(!prepared);prepared=true;for(intv=0;v<n;v++)in_deg[v+1]+=in_deg[v];std::vector<edge_type>new_edges(in_deg.back());autocounter=in_deg;for(auto&&e:edges)new_edges[counter[e.from]++]=e;edges=new_edges;}voidgraph_debug()const{#ifndef __LOCAL
return;#endif
assert(prepared);for(intfrom=0;from<n;from++){std::cerr<<from<<";";for(inti=in_deg[from];i<in_deg[from+1];i++)std::cerr<<edges[i].to<<" ";std::cerr<<"\n";}}};#line 2 "library/graph/ReverseGraph.hpp"
template<typenameGRAPH>GRAPHreverse_graph(constGRAPH&g){GRAPHr(g.n);for(autoe:g.edges){std::swap(e.from,e.to);r.add_arc(e);}r.build();returnr;}#line 4 "library/graph/SCC.hpp"
#define REP_(i, n) for (int i = 0; i < (n); i++)
template<typenameDirectedGraph>classSCC{intn;DirectedGraphG,R;std::vector<int>visit,belong;std::vector<uint8_t>used;voiddfs(intv){used[v]=true;for(intto:G[v])if(!used[to])dfs(to);visit.push_back(v);}voidrdfs(intv,intk){used[v]=true;belong[v]=k;for(intto:R[v])if(!used[to])rdfs(to,k);}public:GraphDAG;std::vector<std::vector<int>>component;SCC(constDirectedGraph&G):n(G.n),G(G),belong(n),used(n,false){assert(G.is_prepared());visit.reserve(n);R=reverse_graph(G);REP_(v,n)if(!used[v])dfs(v);std::ranges::fill(used,false);std::ranges::reverse(visit);intk=0;for(constint&v:visit)if(!used[v])rdfs(v,k++);std::vector<std::vector<int>>edges(k);component.resize(k);REP_(v,n){component[belong[v]].push_back(v);for(intto:G[v])if(belong[v]!=belong[to])edges[belong[v]].push_back(belong[to]);}DAG=Graph(k);REP_(from,k){std::ranges::sort(edges[from]);REP_(i,edges[from].size())if(!i||edges[from][i]!=edges[from][i-1])DAG.add_arc(from,edges[from][i]);}}intoperator[](intk){returnbelong[k];}};#undef REP_