#pragma once
/**
* Author: Teetat T.
* Date: 2024-06-15
* Description: Graph Base
*/template<classT>structEdge{intfrom,to,id;Tcost;Edge(int_from,int_to,T_cost,int_id):from(_from),to(_to),cost(_cost),id(_id){}operatorint()const{returnto;}};template<classT=void,booldirected=false>structGraph{staticconstexprboolis_directed=directed;staticconstexprboolis_weighted=!is_same<T,void>::value;usingcost_type=std::conditional_t<is_weighted,T,int>;usingedge_type=Edge<cost_type>;intn,m;vector<edge_type>edges;vector<vector<edge_type>>g;vector<int>_deg,_indeg,_outdeg;Graph():n(0),m(0){}Graph(int_n):n(_n),m(0),g(_n){}vector<edge_type>&operator[](intu){returng[u];}voidadd_edge(intfrom,intto,cost_typecost=1,intid=-1){assert(0<=from&&from<n&&0<=to&&to<n);if(id==-1)id=m;edges.emplace_back(edge_type(from,to,cost,id));g[from].emplace_back(edge_type(from,to,cost,id));if(!is_directed)g[to].emplace_back(edge_type(to,from,cost,id));m++;}voidcalc_deg(){_deg.assign(n,0);for(auto&e:edges)_deg[e.from]++,_deg[e.to]++;}voidcalc_inout_deg(){_indeg.assign(n,0);_outdeg.assign(n,0);for(auto&e:edges)_outdeg[e.from]++,_indeg[e.to]++;}constvector<int>°_array(){if(_deg.empty())calc_deg();return_deg;}constvector<int>&indeg_array(){if(_indeg.empty())calc_inout_deg();return_indeg;}constvector<int>&outdeg_array(){if(_outdeg.empty())calc_inout_deg();return_outdeg;}intdeg(intu){returndeg_array()[u];}intindeg(intu){returnindeg_array()[u];}intoutdeg(intu){returnoutdeg_array()[u];}Graphreverse(){assert(is_directed);Graphres(n);for(auto&e:edges)res.add_edge(e.to,e.from,e.cost,e.id);returnres;}};template<classT=void,booldirected=false>Graph<T,directed>read_graph(intn,intm,intoffset=1){usingG=Graph<T,directed>;Gg(n);for(inti=0;i<m;i++){intu,v;cin>>u>>v;u-=offset,v-=offset;if(g.is_weighted){typenameG::cost_typew;cin>>w;g.add_edge(u,v,w);}else{g.add_edge(u,v);}}returng;}template<classT=void,booldirected=false>Graph<T,directed>read_tree(intn,intoffset=1){returnread_graph<T,directed>(n,n-1,offset);}
#line 2 "graph/graph-base.hpp"
/**
* Author: Teetat T.
* Date: 2024-06-15
* Description: Graph Base
*/template<classT>structEdge{intfrom,to,id;Tcost;Edge(int_from,int_to,T_cost,int_id):from(_from),to(_to),cost(_cost),id(_id){}operatorint()const{returnto;}};template<classT=void,booldirected=false>structGraph{staticconstexprboolis_directed=directed;staticconstexprboolis_weighted=!is_same<T,void>::value;usingcost_type=std::conditional_t<is_weighted,T,int>;usingedge_type=Edge<cost_type>;intn,m;vector<edge_type>edges;vector<vector<edge_type>>g;vector<int>_deg,_indeg,_outdeg;Graph():n(0),m(0){}Graph(int_n):n(_n),m(0),g(_n){}vector<edge_type>&operator[](intu){returng[u];}voidadd_edge(intfrom,intto,cost_typecost=1,intid=-1){assert(0<=from&&from<n&&0<=to&&to<n);if(id==-1)id=m;edges.emplace_back(edge_type(from,to,cost,id));g[from].emplace_back(edge_type(from,to,cost,id));if(!is_directed)g[to].emplace_back(edge_type(to,from,cost,id));m++;}voidcalc_deg(){_deg.assign(n,0);for(auto&e:edges)_deg[e.from]++,_deg[e.to]++;}voidcalc_inout_deg(){_indeg.assign(n,0);_outdeg.assign(n,0);for(auto&e:edges)_outdeg[e.from]++,_indeg[e.to]++;}constvector<int>°_array(){if(_deg.empty())calc_deg();return_deg;}constvector<int>&indeg_array(){if(_indeg.empty())calc_inout_deg();return_indeg;}constvector<int>&outdeg_array(){if(_outdeg.empty())calc_inout_deg();return_outdeg;}intdeg(intu){returndeg_array()[u];}intindeg(intu){returnindeg_array()[u];}intoutdeg(intu){returnoutdeg_array()[u];}Graphreverse(){assert(is_directed);Graphres(n);for(auto&e:edges)res.add_edge(e.to,e.from,e.cost,e.id);returnres;}};template<classT=void,booldirected=false>Graph<T,directed>read_graph(intn,intm,intoffset=1){usingG=Graph<T,directed>;Gg(n);for(inti=0;i<m;i++){intu,v;cin>>u>>v;u-=offset,v-=offset;if(g.is_weighted){typenameG::cost_typew;cin>>w;g.add_edge(u,v,w);}else{g.add_edge(u,v);}}returng;}template<classT=void,booldirected=false>Graph<T,directed>read_tree(intn,intoffset=1){returnread_graph<T,directed>(n,n-1,offset);}