#pragma once
// This file is a fork of AtCoder Library.#define E6NLAQ_INTERNAL_SCC_HPP
#include<algorithm>
#include<utility>
#include<vector>#include"csr.hpp"namespacee6nlaq{namespaceinternal{// Reference:// R. Tarjan,// Depth-First Search and Linear Graph Algorithmsstructscc_graph{public:explicitscc_graph(intn):_n(n){}intnum_vertices(){return_n;}voidadd_edge(intfrom,intto){edges.push_back({from,{to}});}// @return pair of (# of scc, scc id)std::pair<int,std::vector<int>>scc_ids(){autog=csr<edge>(_n,edges);intnow_ord=0,group_num=0;std::vector<int>visited,low(_n),ord(_n,-1),ids(_n);visited.reserve(_n);autodfs=[&](autoself,intv)->void{low[v]=ord[v]=now_ord++;visited.push_back(v);for(inti=g.start[v];i<g.start[v+1];i++){autoto=g.elist[i].to;if(ord[to]==-1){self(self,to);low[v]=std::min(low[v],low[to]);}else{low[v]=std::min(low[v],ord[to]);}}if(low[v]==ord[v]){while(true){intu=visited.back();visited.pop_back();ord[u]=_n;ids[u]=group_num;if(u==v)break;}group_num++;}};for(inti=0;i<_n;i++){if(ord[i]==-1)dfs(dfs,i);}for(auto&x:ids){x=group_num-1-x;}return{group_num,ids};}std::vector<std::vector<int>>scc(){autoids=scc_ids();intgroup_num=ids.first;std::vector<int>counts(group_num);for(autox:ids.second)counts[x]++;std::vector<std::vector<int>>groups(ids.first);for(inti=0;i<group_num;i++){groups[i].reserve(counts[i]);}for(inti=0;i<_n;i++){groups[ids.second[i]].push_back(i);}returngroups;}private:int_n;structedge{intto;};std::vector<std::pair<int,edge>>edges;};}// namespace internal}// namespace e6nlaq
#line 2 "include/e6nlaq/internal/scc.hpp"
// This file is a fork of AtCoder Library.#define E6NLAQ_INTERNAL_SCC_HPP
#include<algorithm>
#include<utility>
#include<vector>#line 2 "include/e6nlaq/internal/csr.hpp"
// This file is a fork of AtCoder Library.#define E6NLAQ_INTERNAL_CSR_HPP
#line 10 "include/e6nlaq/internal/csr.hpp"
namespacee6nlaq{namespaceinternal{template<classE>structcsr{std::vector<int>start;std::vector<E>elist;explicitcsr(intn,conststd::vector<std::pair<int,E>>&edges):start(n+1),elist(edges.size()){for(autoe:edges){start[e.first+1]++;}for(inti=1;i<=n;i++){start[i]+=start[i-1];}autocounter=start;for(autoe:edges){elist[counter[e.first]++]=e.second;}}};}// namespace internal}// namespace e6nlaq#line 12 "include/e6nlaq/internal/scc.hpp"
namespacee6nlaq{namespaceinternal{// Reference:// R. Tarjan,// Depth-First Search and Linear Graph Algorithmsstructscc_graph{public:explicitscc_graph(intn):_n(n){}intnum_vertices(){return_n;}voidadd_edge(intfrom,intto){edges.push_back({from,{to}});}// @return pair of (# of scc, scc id)std::pair<int,std::vector<int>>scc_ids(){autog=csr<edge>(_n,edges);intnow_ord=0,group_num=0;std::vector<int>visited,low(_n),ord(_n,-1),ids(_n);visited.reserve(_n);autodfs=[&](autoself,intv)->void{low[v]=ord[v]=now_ord++;visited.push_back(v);for(inti=g.start[v];i<g.start[v+1];i++){autoto=g.elist[i].to;if(ord[to]==-1){self(self,to);low[v]=std::min(low[v],low[to]);}else{low[v]=std::min(low[v],ord[to]);}}if(low[v]==ord[v]){while(true){intu=visited.back();visited.pop_back();ord[u]=_n;ids[u]=group_num;if(u==v)break;}group_num++;}};for(inti=0;i<_n;i++){if(ord[i]==-1)dfs(dfs,i);}for(auto&x:ids){x=group_num-1-x;}return{group_num,ids};}std::vector<std::vector<int>>scc(){autoids=scc_ids();intgroup_num=ids.first;std::vector<int>counts(group_num);for(autox:ids.second)counts[x]++;std::vector<std::vector<int>>groups(ids.first);for(inti=0;i<group_num;i++){groups[i].reserve(counts[i]);}for(inti=0;i<_n;i++){groups[ids.second[i]].push_back(i);}returngroups;}private:int_n;structedge{intto;};std::vector<std::pair<int,edge>>edges;};}// namespace internal}// namespace e6nlaq