#define PROBLEM "https://judge.yosupo.jp/problem/aplusb"
#include<algorithm>
#include<cassert>
#include"../../utilities/fast_io.hpp"
#include<set>
#include<string>
#include<vector>#include"../../graph/all.hpp"usingm1une::graph::Graph;voidtest_graph_container(){Graph<int>g(2);assert(g.size()==2);intadded=g.add_vertex();assert(added==2);inte0=g.add_directed_edge(0,1,4);inte1=g.add_edge(1,2,5);assert(e0==0);assert(e1==1);assert(g.edge_count()==2);assert(g[1].size()==1);assert(g.edges().size()==2);autorev=g.reversed();assert(rev[1][0].to==0);}voidtest_edge_alive(){Graph<int>g(4);inte01=g.add_edge(0,1);inte12=g.add_edge(1,2);inte23=g.add_edge(2,3);(void)e01;(void)e23;assert(g.edge_count()==3);assert(g.edges().size()==3);autores=m1une::graph::bfs(g,0);assert(res.dist[3]==3);g.erase_edge(e12);assert(!g.is_edge_alive(e12));assert(g.edges().size()==2);assert(g.edges(true).size()==3);autocut=m1une::graph::bfs(g,0);assert(!cut.reachable(3));autorev=g.reversed();assert(!rev.is_edge_alive(e12));assert(rev.edges().size()==2);g.revive_edge(e12);assert(g.is_edge_alive(e12));autorestored=m1une::graph::bfs(g,0);assert(restored.dist[3]==3);}voidtest_bfs(){Graph<int>g(5);g.add_directed_edge(0,1);g.add_directed_edge(0,2);g.add_directed_edge(1,3);g.add_directed_edge(2,3);g.add_directed_edge(3,4);autores=m1une::graph::bfs(g,0);assert(res.dist[0]==0);assert(res.dist[3]==2);assert(res.dist[4]==3);autopath=res.path(4);assert(path.front()==0);assert(path.back()==4);assert(path.size()==4);}voidtest_dijkstra(){Graph<longlong>g(5);g.add_directed_edge(0,1,4);g.add_directed_edge(0,2,1);g.add_directed_edge(2,1,2);g.add_directed_edge(1,3,1);g.add_directed_edge(2,3,7);g.add_directed_edge(3,4,3);autores=m1une::graph::dijkstra(g,0);assert(res.dist[1]==3);assert(res.dist[4]==7);assert((res.path(4)==std::vector<int>{0,2,1,3,4}));}voidtest_zero_one_bfs(){Graph<int>g(6);g.add_directed_edge(0,1,1);g.add_directed_edge(0,2,0);g.add_directed_edge(2,1,0);g.add_directed_edge(1,3,1);g.add_directed_edge(2,3,1);g.add_directed_edge(3,4,0);autores=m1une::graph::zero_one_bfs(g,0);assert(res.dist[0]==0);assert(res.dist[1]==0);assert(res.dist[3]==1);assert(res.dist[4]==1);assert(!res.reachable(5));assert((res.path(4)==std::vector<int>{0,2,3,4}));automulti=m1une::graph::zero_one_bfs(g,std::vector<int>{1,5});assert(multi.dist[1]==0);assert(multi.dist[4]==1);assert(multi.dist[5]==0);}voidtest_bellman_ford(){Graph<longlong>g(5);g.add_directed_edge(0,1,1);g.add_directed_edge(1,2,-3);g.add_directed_edge(2,3,1);g.add_directed_edge(3,1,1);g.add_directed_edge(0,4,5);autores=m1une::graph::bellman_ford(g,0);assert(res.has_negative_cycle);assert(res.affected_by_negative_cycle(1));assert(res.affected_by_negative_cycle(2));assert(res.affected_by_negative_cycle(3));assert(!res.affected_by_negative_cycle(4));assert(res.dist[4]==5);}voidtest_dag_shortest_path(){Graph<longlong>g(6);g.add_directed_edge(0,1,2);g.add_directed_edge(0,2,5);g.add_directed_edge(1,2,-4);g.add_directed_edge(1,4,10);g.add_directed_edge(2,3,3);g.add_directed_edge(3,4,1);autores=m1une::graph::dag_shortest_path(g,0);assert(res.has_value());assert(res->dist[0]==0);assert(res->dist[2]==-2);assert(res->dist[4]==2);assert(!res->reachable(5));assert((res->path(4)==std::vector<int>{0,1,2,3,4}));assert(res->topological_order.size()==6);automulti=m1une::graph::dag_shortest_path(g,std::vector<int>{1,5});assert(multi.has_value());assert(multi->dist[4]==0);assert(multi->dist[5]==0);g.add_directed_edge(4,1,1);autocyclic=m1une::graph::dag_shortest_path(g,0);assert(!cyclic.has_value());}voidtest_warshall_floyd(){Graph<longlong>g(4);g.add_directed_edge(0,1,3);g.add_directed_edge(1,2,4);g.add_directed_edge(0,2,10);g.add_directed_edge(2,3,-2);autodist=m1une::graph::warshall_floyd(g);assert(dist[0][2]==7);assert(dist[0][3]==5);assert(!m1une::graph::has_negative_cycle(dist));boolchanged=m1une::graph::warshall_floyd_add_directed_edge(dist,3,1,1LL);assert(changed);assert(dist[0][1]==3);assert(dist[2][1]==-1);assert(dist[3][2]==5);changed=m1une::graph::warshall_floyd_add_directed_edge(dist,0,2,100LL);assert(!changed);Graph<longlong>undirected(4);undirected.add_edge(0,1,10);undirected.add_edge(1,2,10);undirected.add_edge(2,3,10);autoudist=m1une::graph::warshall_floyd(undirected);changed=m1une::graph::warshall_floyd_add_undirected_edge(udist,0,3,1LL);assert(changed);assert(udist[0][3]==1);assert(udist[3][0]==1);assert(udist[1][3]==11);}voidtest_topological_sort(){Graph<int>g(4);g.add_directed_edge(0,1);g.add_directed_edge(0,2);g.add_directed_edge(1,3);g.add_directed_edge(2,3);autoorder=m1une::graph::topological_sort(g);assert(order.has_value());std::vector<int>pos(4);for(inti=0;i<4;i++)pos[(*order)[i]]=i;for(intv=0;v<4;v++){for(constauto&e:g[v])assert(pos[e.from]<pos[e.to]);}g.add_directed_edge(3,0);assert(!m1une::graph::is_dag(g));}voidtest_scc(){Graph<int>g(4);g.add_directed_edge(0,1);g.add_directed_edge(1,0);g.add_directed_edge(1,2);g.add_directed_edge(2,3);g.add_directed_edge(3,2);autoscc=m1une::graph::strongly_connected_components(g);assert(scc.count==2);assert(scc.same(0,1));assert(scc.same(2,3));assert(!scc.same(0,2));autodag=scc.dag(g);assert(dag.size()==2);assert(dag.edge_count()==1);}voidtest_lowlink(){Graph<int>g(5);g.add_edge(0,1);g.add_edge(1,2);g.add_edge(2,0);intb0=g.add_edge(1,3);intb1=g.add_edge(3,4);autores=m1une::graph::lowlink(g);assert((res.articulation==std::vector<int>{1,3}));assert((res.bridge_ids==std::vector<int>{b0,b1}));}voidtest_bipartite_and_components(){Graph<int>square(4);square.add_edge(0,1);square.add_edge(1,2);square.add_edge(2,3);square.add_edge(3,0);autobp=m1une::graph::bipartite(square);assert(bp.is_bipartite);assert(bp.color[0]==bp.color[2]);assert((bp.left_vertices==std::vector<int>{0,2}));assert((bp.right_vertices==std::vector<int>{1,3}));assert(bp.left_id[2]==1);assert(bp.right_id[3]==1);autobuilt=m1une::graph::make_bipartite_matching(square);assert(built.has_value());assert(built->matching.left_size()==2);assert(built->matching.right_size()==2);assert(built->matching.max_matching()==2);for(constauto&p:built->matching.matching()){intu=built->left_vertex(p.left);intv=built->right_vertex(p.right);assert(bp.color[u]==0);assert(bp.color[v]==1);assert(square.is_edge_alive(built->original_edge(p.edge_id)));}Graph<int>triangle(3);triangle.add_edge(0,1);triangle.add_edge(1,2);triangle.add_edge(2,0);assert(!m1une::graph::is_bipartite(triangle));assert(!m1une::graph::make_bipartite_matching(triangle).has_value());Graph<int>cc_graph(5);cc_graph.add_edge(0,1);cc_graph.add_edge(2,3);autocc=m1une::graph::connected_components(cc_graph);assert(cc.count==3);assert(cc.same(0,1));assert(cc.same(2,3));assert(!cc.same(0,2));Graph<int>directed(2);directed.add_directed_edge(1,0);assert(m1une::graph::is_bipartite(directed));autoweak=m1une::graph::connected_components(directed);assert(weak.count==1);m1une::graph::BipartiteMatchingbm(3,2);inte00=bm.add_edge(0,0);inte10=bm.add_edge(1,0);inte11=bm.add_edge(1,1);inte21=bm.add_edge(2,1);assert(bm.left_size()==3);assert(bm.right_size()==2);assert(bm.edge_count()==4);assert(bm.get_edge(e10).left==1);assert(bm.max_matching()==2);assert(bm.matching_size()==2);autopairs=bm.matching();assert(pairs.size()==2);autoleft_match=bm.left_match();autoright_match=bm.right_match();for(constauto&p:pairs){assert(left_match[p.left]==p.right);assert(right_match[p.right]==p.left);}autocover=bm.minimum_vertex_cover();assert(cover.left.empty());assert((cover.right==std::vector<int>{0,1}));assert(cover.size()==2);autoindependent=bm.maximum_independent_set();assert((independent.left==std::vector<int>{0,1,2}));assert(independent.right.empty());autoedge_cover=bm.minimum_edge_cover();assert(edge_cover.has_value());assert(edge_cover->size()==3);std::vector<bool>covered_left(3,false),covered_right(2,false);for(intid:*edge_cover){autoedge=bm.get_edge(id);covered_left[edge.left]=true;covered_right[edge.right]=true;}assert((covered_left==std::vector<bool>{true,true,true}));assert((covered_right==std::vector<bool>{true,true}));bm.erase_edge(e11);bm.erase_edge(e21);assert(!bm.is_edge_alive(e21));assert(bm.edges().size()==2);assert(bm.edges(true).size()==4);assert(bm.max_matching()==1);bm.revive_edge(e21);assert(bm.max_matching()==2);m1une::graph::BipartiteMatchingisolated(1,1);assert(!isolated.minimum_edge_cover().has_value());(void)e00;}voidtest_general_matching(){m1une::graph::GeneralMatchingblossom(6);inte01=blossom.add_edge(0,1);inte12=blossom.add_edge(1,2);inte23=blossom.add_edge(2,3);inte34=blossom.add_edge(3,4);inte40=blossom.add_edge(4,0);inte15=blossom.add_edge(1,5);(void)e12;(void)e23;(void)e34;(void)e40;assert(blossom.size()==6);assert(blossom.edge_count()==6);assert(blossom.get_edge(e01).other(0)==1);assert(blossom.max_matching()==3);assert(blossom.matching_size()==3);automate=blossom.mate();automate_edge=blossom.mate_edge();for(intv=0;v<6;v++){assert(mate[v]!=-1);assert(mate[mate[v]]==v);assert(mate_edge[v]!=-1);}autopairs=blossom.matching();assert(pairs.size()==3);for(constauto&p:pairs){assert(mate[p.from]==p.to);assert(mate[p.to]==p.from);}autoedge_cover=blossom.minimum_edge_cover();assert(edge_cover.has_value());assert(edge_cover->size()==3);std::vector<bool>covered(6,false);for(intid:*edge_cover){autoedge=blossom.get_edge(id);covered[edge.from]=true;covered[edge.to]=true;}assert((covered==std::vector<bool>{true,true,true,true,true,true}));blossom.erase_edge(e15);assert(!blossom.is_edge_alive(e15));assert(blossom.edges().size()==5);assert(blossom.edges(true).size()==6);assert(blossom.max_matching()==2);assert(!blossom.minimum_edge_cover().has_value());blossom.revive_edge(e15);assert(blossom.max_matching()==3);m1une::graph::GeneralMatchingtricky(6);tricky.add_edge(0,1);tricky.add_edge(0,4);tricky.add_edge(1,2);tricky.add_edge(3,4);tricky.add_edge(3,5);tricky.add_edge(4,5);assert(tricky.max_matching()==3);for(constauto&p:tricky.matching()){autoe=tricky.get_edge(p.edge_id);assert((e.from==p.from&&e.to==p.to)||(e.from==p.to&&e.to==p.from));}m1une::graph::GeneralMatchingparallel(4);intp01_removed=parallel.add_edge(0,1);parallel.add_edge(0,1);parallel.add_edge(2,3);parallel.erase_edge(p01_removed);assert(parallel.max_matching()==2);autoparallel_mate_edge=parallel.mate_edge();for(intv=0;v<4;v++)assert(parallel.is_edge_alive(parallel_mate_edge[v]));m1une::graph::GeneralMatchingpath(3);path.add_edge(0,1);path.add_edge(1,2);autopath_cover=path.minimum_edge_cover();assert(path_cover.has_value());assert(path_cover->size()==2);m1une::graph::GeneralMatchingbipartite_general(8);intbg03=bipartite_general.add_edge(0,3);bipartite_general.add_edge(0,7);bipartite_general.add_edge(1,4);bipartite_general.add_edge(2,5);bipartite_general.add_edge(6,3);bipartite_general.add_edge(2,7);bipartite_general.erase_edge(bg03);assert(bipartite_general.max_matching()==4);autobipartite_mate=bipartite_general.mate();for(intv=0;v<8;v++){assert(bipartite_mate[v]!=-1);assert(bipartite_mate[bipartite_mate[v]]==v);}m1une::graph::GeneralMatchingisolated(1);assert(!isolated.minimum_edge_cover().has_value());Graph<int>g(4);intg01=g.add_edge(0,1);intg12=g.add_edge(1,2);intg20=g.add_edge(2,0);intg23=g.add_edge(2,3);(void)g01;(void)g12;(void)g20;autobuilt=m1une::graph::make_general_matching(g);assert(built.matching.max_matching()==2);for(constauto&p:built.matching.matching()){assert(g.is_edge_alive(built.original_edge(p.edge_id)));}assert(g.is_edge_alive(g23));}voidtest_maximum_clique_and_independent_set(){Graph<int>g(7);intremoved_clique_edge=-1;for(inti=0;i<4;i++){for(intj=i+1;j<4;j++){intid=g.add_edge(i,j);if(i==0&&j==2)removed_clique_edge=id;}}g.add_edge(4,0);g.add_edge(4,1);g.add_edge(5,1);g.add_edge(5,2);autoclique=m1une::graph::maximum_clique(g);assert(clique.size()==4);assert((clique.vertices==std::vector<int>{0,1,2,3}));assert(m1une::graph::is_clique(g,clique.vertices));assert(m1une::graph::maximum_clique_size(g)==4);autoindependent=m1une::graph::maximum_independent_set(g);assert(independent.size()==4);assert((independent.vertices==std::vector<int>{3,4,5,6}));assert(m1une::graph::is_independent_set(g,independent.vertices));assert(m1une::graph::maximum_independent_set_size(g)==4);autocover=m1une::graph::minimum_vertex_cover(g);assert(cover.size()==3);assert((cover.vertices==std::vector<int>{0,1,2}));assert(m1une::graph::is_vertex_cover(g,cover.vertices));assert(m1une::graph::minimum_vertex_cover_size(g)==3);assert(!m1une::graph::is_clique(g,std::vector<int>{0,2,4}));assert(!m1une::graph::is_independent_set(g,std::vector<int>{4,0}));assert(!m1une::graph::is_vertex_cover(g,std::vector<int>{0,1}));g.erase_edge(removed_clique_edge);assert(m1une::graph::maximum_clique_size(g)==3);g.revive_edge(removed_clique_edge);assert(m1une::graph::maximum_clique_size(g)==4);Graph<int>directed(3);directed.add_directed_edge(0,1);directed.add_directed_edge(1,2);autodirected_clique=m1une::graph::maximum_clique(directed);autodirected_independent=m1une::graph::maximum_independent_set(directed);autodirected_cover=m1une::graph::minimum_vertex_cover(directed);assert(directed_clique.size()==2);assert(directed_independent.size()==2);assert((directed_independent.vertices==std::vector<int>{0,2}));assert((directed_cover.vertices==std::vector<int>{1}));Graph<int>empty(4);assert(m1une::graph::maximum_clique_size(empty)==1);assert(m1une::graph::maximum_independent_set_size(empty)==4);assert(m1une::graph::minimum_vertex_cover(empty).empty());Graph<int>path(6);for(inti=0;i+1<6;i++)path.add_edge(i,i+1);assert(m1une::graph::maximum_independent_set_size(path)==3);assert(m1une::graph::minimum_vertex_cover_size(path)==3);Graph<int>cycle(5);for(inti=0;i<5;i++)cycle.add_edge(i,(i+1)%5);assert(m1une::graph::maximum_independent_set_size(cycle)==2);assert(m1une::graph::minimum_vertex_cover_size(cycle)==3);Graph<int>none(0);assert(m1une::graph::maximum_clique(none).empty());assert(m1une::graph::maximum_independent_set(none).empty());assert(m1une::graph::minimum_vertex_cover(none).empty());}voidtest_cycle_detection(){Graph<int>dg(3);dg.add_directed_edge(0,1);dg.add_directed_edge(1,2);dg.add_directed_edge(2,0);autodirected=m1une::graph::find_directed_cycle(dg);assert(!directed.empty());assert(directed.vertices.front()==directed.vertices.back());assert(directed.edge_ids.size()+1==directed.vertices.size());Graph<int>ug(4);ug.add_edge(0,1);ug.add_edge(1,2);ug.add_edge(2,0);ug.add_edge(2,3);autoundirected=m1une::graph::find_undirected_cycle(ug);assert(!undirected.empty());assert(undirected.vertices.front()==undirected.vertices.back());}voidtest_kruskal(){Graph<longlong>g(4);g.add_edge(0,1,1);g.add_edge(1,2,2);g.add_edge(2,3,3);g.add_edge(0,3,10);g.add_edge(0,2,4);automst=m1une::graph::kruskal(g);assert(mst.cost==6);assert(mst.edges.size()==3);assert(mst.components==1);assert(mst.is_spanning_tree(g.size()));}voidtest_grid(){m1une::graph::Gridgrid(3,4);assert(grid.height()==3);assert(grid.width()==4);assert(grid.size()==12);assert(grid.inside(2,3));assert(!grid.inside(3,0));assert(grid.id(2,3)==11);assert(grid.pos(6)==std::make_pair(1,2));autoadj4=grid.adj4(0,0);std::vector<std::pair<int,int>>expected_adj4={std::pair<int,int>{0,1},std::pair<int,int>{1,0},};assert(adj4==expected_adj4);autoadj8=grid.adj8(1,1);assert(adj8.size()==8);autoadj4_ids=grid.adj4_ids(grid.id(1,1));std::set<int>expected_ids={grid.id(0,1),grid.id(1,2),grid.id(2,1),grid.id(1,0)};assert(std::set<int>(adj4_ids.begin(),adj4_ids.end())==expected_ids);std::vector<std::string>s={"....",".##.","....",};autopassable=[&](inti,intj){returns[i][j]!='#';};autog4=grid.graph4(passable);assert(g4.size()==grid.size());assert(g4[grid.id(1,1)].empty());autores=m1une::graph::bfs(g4,grid.id(0,0));assert(res.dist[grid.id(2,3)]==5);assert(res.dist[grid.id(1,1)]==-1);autog8=grid.graph8(passable);autores8=m1une::graph::bfs(g8,grid.id(0,0));assert(res8.dist[grid.id(2,3)]==4);autoall4=grid.graph4();assert(all4.edge_count()==17);}intmain(){m1une::utilities::FastInputfast_input;m1une::utilities::FastOutputfast_output;test_graph_container();test_edge_alive();test_bfs();test_dijkstra();test_zero_one_bfs();test_bellman_ford();test_dag_shortest_path();test_warshall_floyd();test_topological_sort();test_scc();test_lowlink();test_bipartite_and_components();test_general_matching();test_maximum_clique_and_independent_set();test_cycle_detection();test_kruskal();test_grid();longlonga,b;fast_input>>a>>b;fast_output<<a+b<<'\n';}
#line 1 "verify/graph/graph_algorithms.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/aplusb"
#include<algorithm>
#include<cassert>
#line 1 "utilities/fast_io.hpp"
#line 5 "utilities/fast_io.hpp"
#include<array>
#include<cerrno>
#include<charconv>
#include<cstddef>
#include<cstdio>
#include<cstdlib>
#include<cstdint>
#include<cstring>
#include<iterator>
#include<string>
#include<sys/stat.h>
#include<type_traits>
#include<utility>
#include<unistd.h>
#include<vector>namespacem1une{namespaceutilities{structFastOutput;namespaceinternal{// Shared with the convenience helpers in template.hpp.inlineFastOutput*standard_output_instance=nullptr;// Detect std::begin(x), std::end(x).template<classT,class=void>structis_range:std::false_type{};template<classT>structis_range<T,std::void_t<decltype(std::begin(std::declval<T&>())),decltype(std::end(std::declval<T&>()))>>:std::true_type{};template<classT>inlineconstexprboolis_range_v=is_range<T>::value;template<classT>usingrange_reference_t=decltype(*std::begin(std::declval<T&>()));template<classT>usingrange_value_t=std::remove_cv_t<std::remove_reference_t<range_reference_t<T>>>;template<classT,class=void>structrange_stored_value{usingtype=range_value_t<T>;};template<classT>structrange_stored_value<T,std::void_t<typenamestd::remove_cv_t<std::remove_reference_t<T>>::value_type>>{usingtype=typenamestd::remove_cv_t<std::remove_reference_t<T>>::value_type;};template<classT>usingrange_stored_value_t=typenamerange_stored_value<T>::type;// Treat strings and C strings as scalar output objects, not as ranges.template<classT>structis_char_array:std::false_type{};template<classT,std::size_tN>structis_char_array<T[N]>:std::bool_constant<std::is_same_v<std::remove_cv_t<T>,char>>{};template<classT>structis_string_like:std::bool_constant<std::is_same_v<std::decay_t<T>,std::string>||std::is_same_v<std::decay_t<T>,constchar*>||std::is_same_v<std::decay_t<T>,char*>||is_char_array<std::remove_reference_t<T>>::value>{};template<classT>inlineconstexprboolis_string_like_v=is_string_like<T>::value;// ModInt-like type: x.val() is printable, and x can be assigned from long long.template<classT,class=void>structhas_val_method:std::false_type{};template<classT>structhas_val_method<T,std::void_t<decltype(std::declval<constT&>().val())>>:std::true_type{};template<classT>inlineconstexprboolhas_val_method_v=has_val_method<T>::value;template<classT,class=void>structhas_static_mod_raw:std::false_type{};template<classT>structhas_static_mod_raw<T,std::void_t<decltype(T::mod()),decltype(T::raw(std::declval<uint32_t>()))>>:std::true_type{};template<classT>inlineconstexprboolhas_static_mod_raw_v=has_static_mod_raw<T>::value;// libstdc++ before GCC 16 does not classify __int128 as an integral type in// strict ISO modes such as -std=c++23. Keep the fast-I/O interface independent// of that implementation detail.template<classT>inlineconstexprboolis_integral_v=std::is_integral_v<T>||std::is_same_v<std::remove_cv_t<T>,__int128_t>||std::is_same_v<std::remove_cv_t<T>,__uint128_t>;template<classT>inlineconstexprboolis_signed_v=std::is_signed_v<T>||std::is_same_v<std::remove_cv_t<T>,__int128_t>;template<classT>structmake_unsigned{usingtype=std::make_unsigned_t<T>;};template<>structmake_unsigned<__int128_t>{usingtype=__uint128_t;};template<>structmake_unsigned<__uint128_t>{usingtype=__uint128_t;};template<classT>usingmake_unsigned_t=typenamemake_unsigned<std::remove_cv_t<T>>::type;}// namespace internalstructFastInput{staticconstexprintbuffer_size=1<<20;private:std::FILE*_stream;char_buffer[buffer_size];int_position;int_length;int_file_descriptor;bool_streaming;boolrefill(){_position=0;if(_streaming){ssize_tlength;do{length=::read(_file_descriptor,_buffer,buffer_size);}while(length<0&&errno==EINTR);if(length<=0){_length=0;returnfalse;}_length=int(length);}else{_length=int(std::fread(_buffer,1,buffer_size,_stream));}return_length!=0;}template<classT>boolread_integer_from_stream(T&value){if(!skip_spaces())returnfalse;intc=read_char_raw();boolnegative=false;if(c=='-'){negative=true;c=read_char_raw();}ifconstexpr(internal::is_signed_v<T>){Tresult=0;while('0'<=c&&c<='9'){result=negative?result*10-(c-'0'):result*10+(c-'0');c=read_char_raw();}value=result;}else{Tresult=0;while('0'<=c&&c<='9'){result=result*10+T(c-'0');c=read_char_raw();}value=negative?T(0)-result:result;}returntrue;}boolprepare_number(){if(_length-_position>=64)returntrue;constintremaining=_length-_position;if(remaining>0)std::memmove(_buffer,_buffer+_position,remaining);constintadded=int(std::fread(_buffer+remaining,1,buffer_size-remaining,_stream));_position=0;_length=remaining+added;if(_length<buffer_size)_buffer[_length]='\0';return_length!=0;}public:explicitFastInput(std::FILE*stream=stdin):_stream(stream),_position(0),_length(0),_file_descriptor(::fileno(stream)),_streaming([&]{structstatstatus;return_file_descriptor>=0&&::fstat(_file_descriptor,&status)==0&&!S_ISREG(status.st_mode);}()){}FastInput(constFastInput&)=delete;FastInput&operator=(constFastInput&)=delete;intread_char_raw(){if(_position==_length&&!refill())returnEOF;return_buffer[_position++];}boolskip_spaces(){intc=read_char_raw();while(c!=EOF&&c<=' ')c=read_char_raw();if(c==EOF)returnfalse;--_position;returntrue;}boolread(char&value){if(!skip_spaces())returnfalse;value=char(read_char_raw());returntrue;}boolread(std::string&value){if(!skip_spaces())returnfalse;value.clear();while(true){constintbegin=_position;while(_position<_length&&static_cast<unsignedchar>(_buffer[_position])>' '){++_position;}value.append(_buffer+begin,_position-begin);if(_position<_length){++_position;returntrue;}if(!refill())returntrue;}}boolread(bool&value){intx;if(!read(x))returnfalse;value=x!=0;returntrue;}template<classT>std::enable_if_t<internal::is_integral_v<T>&&!std::is_same_v<std::remove_cv_t<T>,bool>&&!std::is_same_v<std::remove_cv_t<T>,char>,bool>read(T&value){if(_streaming)returnread_integer_from_stream(value);if(!prepare_number())returnfalse;intc=static_cast<unsignedchar>(_buffer[_position++]);while(c<=' ')c=static_cast<unsignedchar>(_buffer[_position++]);boolnegative=false;if(c=='-'){negative=true;c=static_cast<unsignedchar>(_buffer[_position++]);}ifconstexpr(internal::is_signed_v<T>){Tresult=0;while('0'<=c&&c<='9'){constintfirst=c-'0';constintsecond=static_cast<unsignedchar>(_buffer[_position])-'0';if(0<=second&&second<=9){result=negative?result*100-(first*10+second):result*100+(first*10+second);++_position;}else{result=negative?result*10-first:result*10+first;}c=static_cast<unsignedchar>(_buffer[_position++]);}value=result;}else{Tresult=0;while('0'<=c&&c<='9'){constunsignedfirst=unsigned(c-'0');constintsecond=static_cast<unsignedchar>(_buffer[_position])-'0';if(0<=second&&second<=9){result=result*100+T(first*10+unsigned(second));++_position;}else{result=result*10+T(first);}c=static_cast<unsignedchar>(_buffer[_position++]);}value=negative?T(0)-result:result;}if(_position>_length)_position=_length;returntrue;}template<classT>std::enable_if_t<std::is_floating_point_v<T>,bool>read(T&value){if(!skip_spaces())returnfalse;intc=read_char_raw();boolnegative=false;if(c=='-'||c=='+'){negative=c=='-';c=read_char_raw();}longdoubleresult=0;while('0'<=c&&c<='9'){result=result*10+(c-'0');c=read_char_raw();}if(c=='.'){longdoubleplace=0.1L;c=read_char_raw();while('0'<=c&&c<='9'){result+=(c-'0')*place;place*=0.1L;c=read_char_raw();}}if(c=='e'||c=='E'){c=read_char_raw();boolexponent_negative=false;if(c=='-'||c=='+'){exponent_negative=c=='-';c=read_char_raw();}intexponent=0;while('0'<=c&&c<='9'){exponent=exponent*10+(c-'0');c=read_char_raw();}longdoublescale=1;longdoublepower=10;while(exponent>0){if(exponent&1)scale*=power;power*=power;exponent>>=1;}result=exponent_negative?result/scale:result*scale;}value=static_cast<T>(negative?-result:result);returntrue;}template<classT>std::enable_if_t<internal::has_val_method_v<T>&&!internal::is_integral_v<T>&&!internal::is_range_v<T>,bool>read(T&value){longlongx;if(!read(x))returnfalse;ifconstexpr(internal::has_static_mod_raw_v<T>){if(x>=0&&uint64_t(x)<uint64_t(T::mod())){value=T::raw(uint32_t(x));}else{value=T(x);}}else{value=T(x);}returntrue;}template<classFirst,classSecond>boolread(std::pair<First,Second>&value){if(!read(value.first))returnfalse;returnread(value.second);}template<classRange>std::enable_if_t<internal::is_range_v<Range>&&!internal::is_string_like_v<Range>,bool>read(Range&range){usingStoredValue=internal::range_stored_value_t<Range>;constexprboolnested=internal::is_range_v<StoredValue>&&!internal::is_string_like_v<StoredValue>;for(auto&&value:range){ifconstexpr(std::is_same_v<StoredValue,bool>&&!nested){boolx;if(!read(x))returnfalse;value=x;}else{if(!read(value))returnfalse;}}returntrue;}template<classFirst,classSecond,class...Rest>boolread(First&first,Second&second,Rest&...rest){if(!read(first))returnfalse;returnread(second,rest...);}template<classT>FastInput&operator>>(T&value){if(!read(value))std::abort();return*this;}};structFastOutput{staticconstexprintbuffer_size=1<<20;private:inlinestaticconstautodigit_quads=[]{std::array<char,40000>result{};for(inti=0;i<10000;i++){intvalue=i;for(intj=3;j>=0;j--){result[4*i+j]=char('0'+value%10);value/=10;}}returnresult;}();std::FILE*_stream;char_buffer[buffer_size];int_position;int_precision;std::chars_format_float_format;char_range_separator;std::string*_capture=nullptr;template<classT>std::stringformat_cell(constT&value){std::stringresult;structCaptureGuard{std::string*⌖std::string*previous;~CaptureGuard(){target=previous;}}guard{_capture,_capture};_capture=&result;write(value);returnresult;}template<classMatrix>voidwrite_aligned_matrix(constMatrix&matrix){std::vector<std::vector<std::string>>rows;std::vector<std::size_t>widths;for(constauto&row:matrix){auto&cells=rows.emplace_back();std::size_tcolumn=0;for(constauto&value:row){cells.push_back(format_cell(value));if(column==widths.size())widths.push_back(0);widths[column]=std::max(widths[column],cells.back().size());++column;}}boolfirst=true;for(constauto&row:rows){if(!first)write_char('\n');first=false;for(std::size_tcolumn=0;column<row.size();++column){if(column!=0)write_char(_range_separator);for(std::size_tpadding=row[column].size();padding<widths[column];++padding){write_char(' ');}write(row[column]);}}}public:explicitFastOutput(std::FILE*stream=stdout):_stream(stream),_position(0),_precision(6),_float_format(std::chars_format::general),_range_separator(' '){if(_stream==stdout&&internal::standard_output_instance==nullptr){internal::standard_output_instance=this;}}FastOutput(constFastOutput&)=delete;FastOutput&operator=(constFastOutput&)=delete;~FastOutput(){flush();if(internal::standard_output_instance==this){internal::standard_output_instance=nullptr;}}voidflush(){if(_position!=0){std::fwrite(_buffer,1,_position,_stream);_position=0;}std::fflush(_stream);}voidwrite_char(charc){if(_capture!=nullptr){_capture->push_back(c);return;}if(_position==buffer_size)flush();_buffer[_position++]=c;}voidwrite(constchar*s){while(*s!='\0')write_char(*s++);}voidwrite(conststd::string&s){if(_capture!=nullptr){_capture->append(s);return;}std::size_tposition=0;while(position<s.size()){if(_position==buffer_size)flush();conststd::size_tcopied=std::min<std::size_t>(buffer_size-_position,s.size()-position);std::memcpy(_buffer+_position,s.data()+position,copied);_position+=int(copied);position+=copied;}}voidwrite(charc){write_char(c);}voidwrite(boolvalue){write_char(value?'1':'0');}template<classT>std::enable_if_t<std::is_floating_point_v<T>>write(Tvalue){chardigits[128];auto[end,error]=std::to_chars(digits,digits+sizeof(digits),value,_float_format,_precision);if(error!=std::errc())std::abort();for(constchar*pointer=digits;pointer!=end;pointer++){write_char(*pointer);}}template<classT>std::enable_if_t<internal::is_integral_v<T>&&!std::is_same_v<std::remove_cv_t<T>,bool>&&!std::is_same_v<std::remove_cv_t<T>,char>>write(Tvalue){usingRaw=std::remove_cv_t<T>;usingUnsigned=internal::make_unsigned_t<Raw>;Unsignedmagnitude;ifconstexpr(internal::is_signed_v<Raw>){if(value<0){write_char('-');magnitude=Unsigned(0)-Unsigned(value);}else{magnitude=Unsigned(value);}}else{magnitude=value;}if(magnitude==0){write_char('0');return;}unsignedchunks[16];intcount=0;while(magnitude>=10000){constUnsignedquotient=magnitude/10000;chunks[count++]=unsigned(magnitude-quotient*10000);magnitude=quotient;}if(_capture==nullptr&&_position>buffer_size-64)flush();charcaptured[64];char*constbegin=_capture!=nullptr?captured:_buffer+_position;char*destination=begin;constunsignedleading=unsigned(magnitude);constchar*first=digit_quads.data()+4*leading;intskip=leading<10?3:leading<100?2:leading<1000?1:0;for(;skip<4;skip++)*destination++=first[skip];while(count--){constchar*digits=digit_quads.data()+4*chunks[count];std::memcpy(destination,digits,4);destination+=4;}if(_capture!=nullptr){_capture->append(begin,destination-begin);}else{_position+=int(destination-begin);}}template<classT>std::enable_if_t<internal::has_val_method_v<T>&&!internal::is_integral_v<T>&&!internal::is_range_v<T>>write(constT&value){write(value.val());}template<classFirst,classSecond>voidwrite(conststd::pair<First,Second>&value){write(value.first);write_char(' ');write(value.second);}template<classRange>std::enable_if_t<internal::is_range_v<Range>&&!internal::is_string_like_v<Range>>write(constRange&range){usingStoredValue=internal::range_stored_value_t<constRange>;constexprboolnested=internal::is_range_v<StoredValue>&&!internal::is_string_like_v<StoredValue>;boolfirst=true;for(constauto&value:range){if(!first)write_char(nested?'\n':_range_separator);first=false;ifconstexpr(std::is_same_v<StoredValue,bool>&&!nested){write(static_cast<bool>(value));}else{write(value);}}}template<classFirst,class...Rest>voidprint(constFirst&first,constRest&...rest){write(first);((write_char(' '),write(rest)),...);}voidprintln(){write_char('\n');}voidset_precision(intprecision){_precision=precision;}voidset_fixed(intprecision=6){_float_format=std::chars_format::fixed;_precision=precision;}voidset_general(intprecision=6){_float_format=std::chars_format::general;_precision=precision;}voidset_range_separator(charseparator){_range_separator=separator;}template<classMatrix>voidwrite_aligned(constMatrix&matrix){usingRow=internal::range_stored_value_t<constMatrix>;usingCell=internal::range_stored_value_t<constRow>;static_assert(internal::is_range_v<Row>&&!internal::is_string_like_v<Row>,"write_aligned requires a two-dimensional range");static_assert(!internal::is_range_v<Cell>||internal::is_string_like_v<Cell>,"write_aligned requires scalar cells");write_aligned_matrix(matrix);}template<classMatrix>voidprintln_aligned(constMatrix&matrix){write_aligned(matrix);write_char('\n');}template<class...Args>voidprintln(constArgs&...args){print(args...);write_char('\n');}template<classT>FastOutput&operator<<(constT&value){write(value);return*this;}};}// namespace utilities}// namespace m1une#line 6 "verify/graph/graph_algorithms.test.cpp"
#include<set>
#line 9 "verify/graph/graph_algorithms.test.cpp"
#line 1 "graph/all.hpp"
#line 1 "graph/counting.hpp"
#line 6 "graph/counting.hpp"
#include<optional>
#line 9 "graph/counting.hpp"
#line 1 "math/fps/convolution.hpp"
#line 9 "math/fps/convolution.hpp"
#include<new>
#line 13 "math/fps/convolution.hpp"
#if defined(__GNUC__) && !defined(__clang__) && \
(defined(__x86_64__) || defined(__i386__)) && \
!defined(M1UNE_FPS_DISABLE_X86_SIMD)
#include<immintrin.h>
#define M1UNE_FPS_HAS_X86_SIMD 1
#pragma GCC push_options
#pragma GCC target("avx2,bmi")
#endif
#line 1 "math/fps/internal/ntt998_faster.hpp"
#ifdef M1UNE_FPS_HAS_X86_SIMD
#line 9 "math/fps/internal/ntt998_faster.hpp"
#include<immintrin.h>namespacem1une{namespacefps{namespaceinternal{namespacefast998_v2{// Fixed-modulus AVX2 transform with an in-register degree-8 residue product.usingu32=unsigned;usingu64=unsignedlonglong;usingidt=std::size_t;usingI256=__m256i;inlinevoidstore256(void*p,I256x){_mm256_store_si256((I256*)p,x);}inlineI256load256(constvoid*p){return_mm256_load_si256((constI256*)p);}constexpru32shrk(u32x,u32M){returnstd::min(x,x-M);}constexpru32dilt(u32x,u32M){returnstd::min(x,x+M);}constexpru32reduce(u64x,u32niv,u32M){return(x+u64(u32(x)*niv)*M)>>32;}constexpru32mul(u32x,u32y,u32niv,u32M){returnreduce(u64(x)*y,niv,M);}constexpru32mul_s(u32x,u32y,u32niv,u32M){returnshrk(reduce(u64(x)*y,niv,M),M);}constexpru32qpw(u32a,u32b,u32niv,u32M,u32r){for(;b;b>>=1,a=mul(a,a,niv,M)){if(b&1){r=mul(r,a,niv,M);}}returnr;}constexpru32qpw_s(u32a,u32b,u32niv,u32M,u32r){returnshrk(qpw(a,b,niv,M,r),M);}inlineI256shrk32(I256x,I256M){return_mm256_min_epu32(x,_mm256_sub_epi32(x,M));}inlineI256dilt32(I256x,I256M){return_mm256_min_epu32(x,_mm256_add_epi32(x,M));}inlineI256Ladd32(I256x,I256y,I256){return_mm256_add_epi32(x,y);}inlineI256Lsub32(I256x,I256y,I256M){return_mm256_add_epi32(_mm256_sub_epi32(x,y),M);}inlineI256add32(I256x,I256y,I256M){returnshrk32(_mm256_add_epi32(x,y),M);}inlineI256sub32(I256x,I256y,I256M){returndilt32(_mm256_sub_epi32(x,y),M);}template<intmsk>inlineI256neg32_m(I256x,I256M){return_mm256_blend_epi32(x,_mm256_sub_epi32(M,x),msk);}inlineI256reduce(I256a,I256b,I256niv,I256M){I256c=_mm256_mul_epu32(a,niv),d=_mm256_mul_epu32(b,niv);c=_mm256_mul_epu32(c,M),d=_mm256_mul_epu32(d,M);return_mm256_blend_epi32(_mm256_srli_epi64(_mm256_add_epi64(a,c),32),_mm256_add_epi64(b,d),0xaa);}inlineI256mul(I256a,I256b,I256niv,I256M){returnreduce(_mm256_mul_epu32(a,b),_mm256_mul_epu32(_mm256_srli_epi64(a,32),_mm256_srli_epi64(b,32)),niv,M);}inlineI256mul_s(I256a,I256b,I256niv,I256M){returnshrk32(mul(a,b,niv,M),M);}inlineI256mul_bsm(I256a,I256b,I256niv,I256M){returnreduce(_mm256_mul_epu32(a,b),_mm256_mul_epu32(_mm256_srli_epi64(a,32),b),niv,M);}inlineI256mul_bsmfxd(I256a,I256b,I256bniv,I256M){I256cc=_mm256_mul_epu32(a,bniv),dd=_mm256_mul_epu32(_mm256_srli_epi64(a,32),bniv);I256c=_mm256_mul_epu32(a,b),d=_mm256_mul_epu32(_mm256_srli_epi64(a,32),b);cc=_mm256_mul_epu32(cc,M),dd=_mm256_mul_epu32(dd,M);return_mm256_blend_epi32(_mm256_srli_epi64(_mm256_add_epi64(c,cc),32),_mm256_add_epi64(d,dd),0xaa);}inlineI256mul_bfxd(I256a,I256b,I256bniv,I256M){I256cc=_mm256_mul_epu32(a,bniv),dd=_mm256_mul_epu32(_mm256_srli_epi64(a,32),_mm256_srli_epi64(bniv,32));I256c=_mm256_mul_epu32(a,b),d=_mm256_mul_epu32(_mm256_srli_epi64(a,32),_mm256_srli_epi64(b,32));cc=_mm256_mul_epu32(cc,M),dd=_mm256_mul_epu32(dd,M);return_mm256_blend_epi32(_mm256_srli_epi64(_mm256_add_epi64(c,cc),32),_mm256_add_epi64(d,dd),0xaa);}inlineI256mul_upd_rt(I256a,I256bu,I256M){I256cc=_mm256_mul_epu32(a,bu),c=_mm256_mul_epu32(a,_mm256_srli_epi64(bu,32));cc=_mm256_mul_epu32(cc,M);returnshrk32(_mm256_srli_epi64(_mm256_add_epi64(c,cc),32),M);}constexprauto_mxlg=26,_lg_itth=6;constexprauto_itth=idt(1)<<_lg_itth;static_assert(_lg_itth%2==0);structFNTT32_info{u32mod,mod2,niv,one,r2,r3,img,imgniv,RT1[_mxlg];alignas(32)std::array<u32,8>rt3[_mxlg-2],rt3i[_mxlg-2],bwbr,bwb,bwbi,rt4[_mxlg-3],rt4niv[_mxlg-3],rt4i[_mxlg-3],rt4iniv[_mxlg-3],pr2,pr4,pr2niv,pr4niv,pr2i,pr2iniv,pr4i,pr4iniv;constexprFNTT32_info(constu32m):mod(m),mod2(m*2),niv([&]{u32n=2+m;for(inti=0;i<4;++i){n*=2+m*n;}returnn;}()),one((-m)%m),r2((-u64(m))%m),r3(mul_s(r2,r2,niv,m)),img{},imgniv{},RT1{},rt3{},rt3i{},bwbr{},bwb{},bwbi{},rt4{},rt4niv{},rt4i{},rt4iniv{},pr2{},pr4{},pr2niv{},pr4niv{},pr2i{},pr2iniv{},pr4i{},pr4iniv{}{constintk=__builtin_ctz(m-1);u32_g=mul(3,r2,niv,mod);for(;;++_g){if(qpw_s(_g,mod>>1,niv,mod,one)!=one){break;}}_g=qpw(_g,mod>>k,niv,mod,one);u32rt1[_mxlg-1],rt1i[_mxlg-1];rt1[k-2]=_g,rt1i[k-2]=qpw(_g,mod-2,niv,mod,one);for(inti=k-2;i>0;--i){rt1[i-1]=mul(rt1[i],rt1[i],niv,mod);rt1i[i-1]=mul(rt1i[i],rt1i[i],niv,mod);}RT1[k-1]=qpw_s(_g,3,niv,mod,one);for(inti=k-1;i>0;--i){RT1[i-1]=mul_s(RT1[i],RT1[i],niv,mod);}img=rt1[0],imgniv=img*niv;bwbr={one,0,one,0,one};bwb={rt1[1],0,rt1[0],0,mod-mul_s(rt1[0],rt1[1],niv,mod)};bwbi={rt1i[1],0,rt1i[0],0,mul_s(rt1i[0],rt1i[1],niv,mod)};u32pr=one,pri=one;for(inti=0;i<k-2;++i){constu32r=mul_s(pr,rt1[i+1],niv,mod),ri=mul_s(pri,rt1i[i+1],niv,mod);constu32r2=mul_s(r,r,niv,mod),r2i=mul_s(ri,ri,niv,mod);constu32r3=mul_s(r,r2,niv,mod),r3i=mul_s(ri,r2i,niv,mod);rt3[i]={r*niv,r,r2*niv,r2,r3*niv,r3};rt3i[i]={ri*niv,ri,r2i*niv,r2i,r3i*niv,r3i};pr=mul(pr,rt1i[i+1],niv,mod),pri=mul(pri,rt1[i+1],niv,mod);}pr=one,pri=one;for(inti=0;i<k-3;++i){constu32r=mul_s(pr,rt1[i+2],niv,mod),ri=mul_s(pri,rt1i[i+2],niv,mod);rt4[i][0]=rt4i[i][0]=one;for(intj=1;j<8;++j){rt4[i][j]=mul_s(rt4[i][j-1],r,niv,mod);rt4i[i][j]=mul_s(rt4i[i][j-1],ri,niv,mod);}for(intj=0;j<8;++j){rt4niv[i][j]=rt4[i][j]*niv;rt4iniv[i][j]=rt4i[i][j]*niv;}pr=mul(pr,rt1i[i+2],niv,mod),pri=mul(pri,rt1[i+2],niv,mod);}pr2={one,one,one,img,one,one,one,img};pr4={one,one,one,one,one,rt1[1],img,mul_s(img,rt1[1],niv,mod)};constu32nr2=mod-r2,imgr2=mul_s(img,r2,niv,mod);pr2i={nr2,nr2,nr2,imgr2,nr2,nr2,nr2,imgr2};pr4i={one,one,one,one,one,rt1i[1],rt1i[0],mul_s(rt1i[0],rt1i[1],niv,mod)};for(intj=0;j<8;++j){pr2niv[j]=pr2[j]*niv,pr4niv[j]=pr4[j]*niv;pr2iniv[j]=pr2i[j]*niv,pr4iniv[j]=pr4i[j]*niv;}}};inlinevoidvector_dif(I256*constf,constidtn,constFNTT32_info*info){alignas(32)std::array<u32,8>st_1[_mxlg>>1];constI256Mod=_mm256_set1_epi32(info->mod),Mod2=_mm256_set1_epi32(info->mod2),Niv=_mm256_set1_epi32(info->niv);constI256Img=_mm256_set1_epi32(info->img),ImgNiv=_mm256_set1_epi32(info->imgniv),id=_mm256_setr_epi32(0,2,0,4,0,2,0,4);constintlgn=__builtin_ctzll(n);std::fill(st_1,st_1+(lgn>>1),info->bwb);constidtnn=n>>(lgn&1),m=std::min(n,_itth),mm=std::min(nn,_itth);// I256 rr=_mm256_set1_epi32(info->one);if(nn!=n){for(idti=0;i<nn;++i){autoconstp0=f+i,p1=f+nn+i;constautof0=load256(p0),f1=load256(p1);constautog0=add32(f0,f1,Mod2),g1=Lsub32(f0,f1,Mod2);store256(p0,g0),store256(p1,g1);}}for(idtL=nn>>2;L>0;L>>=2){for(idti=0;i<L;++i){autoconstp0=f+i,p1=p0+L,p2=p1+L,p3=p2+L;constautof1=load256(p1),f3=load256(p3),f2=load256(p2),f0=load256(p0);constautog3=mul_bsmfxd(Lsub32(f1,f3,Mod2),Img,ImgNiv,Mod),g1=add32(f1,f3,Mod2);constautog0=add32(f0,f2,Mod2),g2=sub32(f0,f2,Mod2);constautoh0=add32(g0,g1,Mod2),h1=Lsub32(g0,g1,Mod2);constautoh2=Ladd32(g2,g3,Mod2),h3=Lsub32(g2,g3,Mod2);store256(p0,h0),store256(p1,h1),store256(p2,h2),store256(p3,h3);}}for(idtj=0;j<n;j+=m){intt=((j==0)?std::min(_lg_itth,lgn):__builtin_ctzll(j))&-2,p=(t-2)>>1;for(idtL=(idt(1)<<t)>>2;L>=_itth;L>>=2,t-=2,--p){autort=load256(st_1+p);constautor1=_mm256_permutevar8x32_epi32(rt,id);constautor1Niv=_mm256_permutevar8x32_epi32(_mm256_mul_epu32(rt,Niv),id);rt=mul_upd_rt(rt,load256(info->rt3+__builtin_ctzll(~j>>t)),Mod);constautor2=_mm256_shuffle_epi32(r1,_MM_PERM_BBBB),nr3=_mm256_shuffle_epi32(r1,_MM_PERM_DDDD);constautor2Niv=_mm256_shuffle_epi32(r1Niv,_MM_PERM_BBBB),nr3Niv=_mm256_shuffle_epi32(r1Niv,_MM_PERM_DDDD);store256(st_1+p,rt);for(idti=0;i<L;++i){autoconstp0=f+i+j,p1=p0+L,p2=p1+L,p3=p2+L;constautof1=load256(p1),f3=load256(p3),f2=load256(p2),f0=load256(p0);constautog1=mul_bsmfxd(f1,r1,r1Niv,Mod),ng3=mul_bsmfxd(f3,nr3,nr3Niv,Mod);constautog2=mul_bsmfxd(f2,r2,r2Niv,Mod),g0=shrk32(f0,Mod2);constautoh3=mul_bsmfxd(Ladd32(g1,ng3,Mod2),Img,ImgNiv,Mod),h1=sub32(g1,ng3,Mod2);constautoh0=add32(g0,g2,Mod2),h2=sub32(g0,g2,Mod2);constautou0=Ladd32(h0,h1,Mod2),u1=Lsub32(h0,h1,Mod2);constautou2=Ladd32(h2,h3,Mod2),u3=Lsub32(h2,h3,Mod2);store256(p0,u0),store256(p1,u1),store256(p2,u2),store256(p3,u3);}}I256*constg=f+j;for(idtl=mm,L=mm>>2;L;l=L,L>>=2,t-=2,--p){autort=load256(st_1+p);for(idti=(j==0?l:0),k=(j+i)>>t;i<m;i+=l,++k){constautor1=_mm256_permutevar8x32_epi32(rt,id);constautor2=_mm256_shuffle_epi32(r1,_MM_PERM_BBBB);constautonr3=_mm256_shuffle_epi32(r1,_MM_PERM_DDDD);for(idtj=0;j<L;++j){autoconstp0=g+i+j,p1=p0+L,p2=p1+L,p3=p2+L;constautof1=load256(p1),f3=load256(p3),f2=load256(p2),f0=load256(p0);constautog1=mul_bsm(f1,r1,Niv,Mod),ng3=mul_bsm(f3,nr3,Niv,Mod);constautog2=mul_bsm(f2,r2,Niv,Mod),g0=shrk32(f0,Mod2);constautoh3=mul_bsmfxd(Ladd32(g1,ng3,Mod2),Img,ImgNiv,Mod),h1=sub32(g1,ng3,Mod2);constautoh0=add32(g0,g2,Mod2),h2=sub32(g0,g2,Mod2);constautou0=Ladd32(h0,h1,Mod2),u1=Lsub32(h0,h1,Mod2);constautou2=Ladd32(h2,h3,Mod2),u3=Lsub32(h2,h3,Mod2);store256(p0,u0),store256(p1,u1),store256(p2,u2),store256(p3,u3);}rt=mul_upd_rt(rt,load256(info->rt3+__builtin_ctzll(~k)),Mod);}store256(st_1+p,rt);}// const auto pr2=load256(&info->pr2),pr4=load256(&info->pr4);// const auto pr2Niv=load256(&info->pr2niv),pr4Niv=load256(&info->pr4niv);// for(idt i=j;i<j+m;++i){// auto fi=load256(f+i);// fi=mul(fi,rr,Niv,Mod);// rr=shrk32(mul_bfxd(rr,load256(info->rt4+__builtin_ctzll(~i)),load256(info->rt4niv+__builtin_ctzll(~i)),Mod),Mod);// fi=mul_bfxd(Ladd32(neg32_m<0xf0>(fi,Mod2),_mm256_permute2x128_si256(fi,fi,1),Mod2),pr4,pr4Niv,Mod);// fi=mul_bfxd(Ladd32(neg32_m<0xcc>(fi,Mod2),_mm256_shuffle_epi32(fi,0x4e),Mod2),pr2,pr2Niv,Mod);// fi=sub32(_mm256_shuffle_epi32(fi,0xb1),neg32_m<0x55>(fi,Mod2),Mod2);// store256(f+i,fi);// }}}template<boolshrk=false>inlinevoidvector_dit(I256*constf,idtn,constFNTT32_info*constinfo){alignas(32)std::array<u32,8>st_1[_mxlg>>1];constI256Mod=_mm256_set1_epi32(info->mod),Mod2=_mm256_set1_epi32(info->mod2),Niv=_mm256_set1_epi32(info->niv);constI256Img=_mm256_set1_epi32(info->img),ImgNiv=_mm256_set1_epi32(info->imgniv),id=_mm256_setr_epi32(0,2,0,4,0,2,0,4);constintlgn=__builtin_ctzll(n);std::fill(st_1,st_1+(_lg_itth>>1),info->bwbr);std::fill(st_1+(_lg_itth>>1),st_1+(_mxlg>>1),info->bwbi);constidtnn=n>>(lgn&1),mm=std::min(nn,_itth);// I256 rr=_mm256_set1_epi32((info->mod-1)>>(lgn+3));for(idtj=0;j<n;j+=mm){// const auto pr2=load256(&info->pr2i),pr4=load256(&info->pr4i);// const auto pr2Niv=load256(&info->pr2iniv),pr4Niv=load256(&info->pr4iniv);// for(idt i=j;i<j+mm;++i){// auto fi=load256(f+i);// const auto rt=rr;// rr=shrk32(mul_bfxd(rr,load256(info->rt4i+__builtin_ctzll(~i)),load256(info->rt4iniv+__builtin_ctzll(~i)),Mod),Mod);// fi=mul_bfxd(Ladd32(neg32_m<0xaa>(fi,Mod2),_mm256_shuffle_epi32(fi,0xb1),Mod2),pr2,pr2Niv,Mod);// fi=mul_bfxd(Ladd32(neg32_m<0xcc>(fi,Mod2),_mm256_shuffle_epi32(fi,0x4e),Mod2),pr4,pr4Niv,Mod);// fi=mul(Ladd32(neg32_m<0xf0>(fi,Mod2),_mm256_permute2x128_si256(fi,fi,1),Mod2),rt,Niv,Mod);// store256(f+i,fi);// }I256*constg=f+j;intt=2,p=0;for(idtl=4,L=1;l<=mm;L=l,l<<=2,t+=2,++p){autort=load256(st_1+p);for(idti=0,k=j>>t;i<mm;i+=l,++k){constautor1=_mm256_permutevar8x32_epi32(rt,id);constautor2=_mm256_shuffle_epi32(r1,_MM_PERM_BBBB);constautor3=_mm256_shuffle_epi32(r1,_MM_PERM_DDDD);for(idtj=0;j<L;++j){autoconstp0=g+i+j,p1=p0+L,p2=p1+L,p3=p2+L;constautof0=load256(p0),f1=load256(p1),f2=load256(p2),f3=load256(p3);constautog0=add32(f0,f1,Mod2),g1=sub32(f0,f1,Mod2);constautog2=add32(f2,f3,Mod2),g3=mul_bsmfxd(Lsub32(f3,f2,Mod2),Img,ImgNiv,Mod);constautoh0=Ladd32(g0,g2,Mod2),h1=Ladd32(g1,g3,Mod2);constautoh2=Lsub32(g0,g2,Mod2),h3=Lsub32(g1,g3,Mod2);constautou0=shrk32(h0,Mod2),u1=mul_bsm(h1,r1,Niv,Mod);constautou2=mul_bsm(h2,r2,Niv,Mod),u3=mul_bsm(h3,r3,Niv,Mod);store256(p0,u0),store256(p1,u1),store256(p2,u2),store256(p3,u3);}rt=mul_upd_rt(rt,load256(info->rt3i+__builtin_ctzll(~k)),Mod);}store256(st_1+p,rt);}inttt=std::min(__builtin_ctzll(~(j>>_lg_itth))+_lg_itth,lgn);for(idtL=_itth,l=L<<2;t<=tt;L=l,l<<=2,t+=2,++p){if((j+_itth)==l){if(shrk&&l==n){for(idti=0;i<L;++i){autoconstp0=f+i,p1=p0+L,p2=p1+L,p3=p2+L;constautof2=load256(p2),f3=load256(p3),f0=load256(p0),f1=load256(p1);constautog3=mul_bsmfxd(Lsub32(f3,f2,Mod2),Img,ImgNiv,Mod),g2=add32(f2,f3,Mod2);constautog0=add32(f0,f1,Mod2),g1=sub32(f0,f1,Mod2);constautoh0=add32(g0,g2,Mod2),h1=add32(g1,g3,Mod2);constautoh2=sub32(g0,g2,Mod2),h3=sub32(g1,g3,Mod2);constautou0=shrk32(h0,Mod),u1=shrk32(h1,Mod);constautou2=shrk32(h2,Mod),u3=shrk32(h3,Mod);store256(p0,u0),store256(p1,u1),store256(p2,u2),store256(p3,u3);}}else{for(idti=0;i<L;++i){autoconstp0=f+i,p1=p0+L,p2=p1+L,p3=p2+L;constautof2=load256(p2),f3=load256(p3),f0=load256(p0),f1=load256(p1);constautog3=mul_bsmfxd(Lsub32(f3,f2,Mod2),Img,ImgNiv,Mod),g2=add32(f2,f3,Mod2);constautog0=add32(f0,f1,Mod2),g1=sub32(f0,f1,Mod2);constautoh0=add32(g0,g2,Mod2),h1=add32(g1,g3,Mod2);constautoh2=sub32(g0,g2,Mod2),h3=sub32(g1,g3,Mod2);store256(p0,h0),store256(p1,h1),store256(p2,h2),store256(p3,h3);}}}else{autort=load256(st_1+p);constautor1=_mm256_permutevar8x32_epi32(rt,id);constautor1Niv=_mm256_permutevar8x32_epi32(_mm256_mul_epu32(rt,Niv),id);rt=mul_upd_rt(rt,load256(info->rt3i+__builtin_ctzll(~j>>t)),Mod);constautor2=_mm256_shuffle_epi32(r1,_MM_PERM_BBBB),r3=_mm256_shuffle_epi32(r1,_MM_PERM_DDDD);constautor2Niv=_mm256_shuffle_epi32(r1Niv,_MM_PERM_BBBB),r3Niv=_mm256_shuffle_epi32(r1Niv,_MM_PERM_DDDD);store256(st_1+p,rt);for(idti=0;i<L;++i){autoconstp0=f+j+_itth-l+i,p1=p0+L,p2=p1+L,p3=p2+L;constautof0=load256(p0),f1=load256(p1),f2=load256(p2),f3=load256(p3);constautog0=add32(f0,f1,Mod2),g1=sub32(f0,f1,Mod2);constautog2=add32(f2,f3,Mod2),g3=mul_bsmfxd(Lsub32(f3,f2,Mod2),Img,ImgNiv,Mod);constautoh0=Ladd32(g0,g2,Mod2),h1=Ladd32(g1,g3,Mod2);constautoh2=Lsub32(g0,g2,Mod2),h3=Lsub32(g1,g3,Mod2);constautou0=shrk32(h0,Mod2),u1=mul_bsmfxd(h1,r1,r1Niv,Mod);constautou2=mul_bsmfxd(h2,r2,r2Niv,Mod),u3=mul_bsmfxd(h3,r3,r3Niv,Mod);store256(p0,u0),store256(p1,u1),store256(p2,u2),store256(p3,u3);}}}}if(shrk&&nn==n&&n<=_itth){for(idti=0;i<n;++i){constautof0=load256(f+i);store256(f+i,shrk32(f0,Mod));}}if(nn!=n){for(idti=0;i<nn;++i){autoconstp0=f+i,p1=f+nn+i;constautof0=load256(p0),f1=load256(p1);constautog0=add32(f0,f1,Mod2),g1=sub32(f0,f1,Mod2);ifconstexpr(shrk){constautoh0=shrk32(g0,Mod),h1=shrk32(g1,Mod);store256(p0,h0),store256(p1,h1);}else{store256(p0,g0),store256(p1,g1);}}}}// Returns fx * f[0,8) * g[0,8) (mod x^8 - ww).[[gnu::always_inline]]inlineI256convolve8(constI256*f,constI256*g,I256ww,I256fx,I256Niv,I256Mod,I256Mod2){constautoraa=load256(f),rbb=load256(g);constautotaa=shrk32(raa,Mod2),bb=shrk32(mul_bsm(rbb,fx,Niv,Mod),Mod);constautoaw=shrk32(mul_bsm(taa,ww,Niv,Mod),Mod);constautoaa=shrk32(taa,Mod);constautoawa=_mm256_permute2x128_si256(aa,aw,3);constautob0=_mm256_permute4x64_epi64(bb,0x00),b1=_mm256_shuffle_epi32(b0,_MM_PERM_CDAB);constautoa0=aa,a1=_mm256_srli_epi64(a0,32);constautoaw7=_mm256_alignr_epi8(aa,awa,12);autores00=_mm256_mul_epu32(a0,b0);autores01=_mm256_mul_epu32(a1,b0);autores10=_mm256_mul_epu32(aw7,b1);autores11=_mm256_mul_epu32(a0,b1);constautob2=_mm256_permute4x64_epi64(bb,0x55),b3=_mm256_shuffle_epi32(b2,_MM_PERM_CDAB);constautoaw6=_mm256_alignr_epi8(aa,awa,8);constautoaw5=_mm256_alignr_epi8(aa,awa,4);res00=_mm256_add_epi64(res00,_mm256_mul_epu32(aw6,b2));res01=_mm256_add_epi64(res01,_mm256_mul_epu32(aw7,b2));res10=_mm256_add_epi64(res10,_mm256_mul_epu32(aw5,b3));res11=_mm256_add_epi64(res11,_mm256_mul_epu32(aw6,b3));constautob4=_mm256_permute4x64_epi64(bb,0xaa),b5=_mm256_shuffle_epi32(b4,_MM_PERM_CDAB);constautoaw3=_mm256_alignr_epi8(awa,aw,12);res00=_mm256_add_epi64(res00,_mm256_mul_epu32(awa,b4));res01=_mm256_add_epi64(res01,_mm256_mul_epu32(aw5,b4));res10=_mm256_add_epi64(res10,_mm256_mul_epu32(aw3,b5));res11=_mm256_add_epi64(res11,_mm256_mul_epu32(awa,b5));constautob6=_mm256_permute4x64_epi64(bb,0xff),b7=_mm256_shuffle_epi32(b6,_MM_PERM_CDAB);constautoaw2=_mm256_alignr_epi8(awa,aw,8);constautoaw1=_mm256_alignr_epi8(awa,aw,4);res00=_mm256_add_epi64(res00,_mm256_mul_epu32(aw2,b6));res01=_mm256_add_epi64(res01,_mm256_mul_epu32(aw3,b6));res10=_mm256_add_epi64(res10,_mm256_mul_epu32(aw1,b7));res11=_mm256_add_epi64(res11,_mm256_mul_epu32(aw2,b7));res00=_mm256_add_epi64(res00,res10);res01=_mm256_add_epi64(res01,res11);returnshrk32(reduce(res00,res01,Niv,Mod),Mod2);}inlinevoidvector_convolution_direct(I256*f,constI256*g,idtlm,constFNTT32_info*constinfo){u32RR=info->one;constautomod=info->mod,niv=info->niv;constautoFx=_mm256_set1_epi32(mul_s((mod-((mod-1)>>(__builtin_ctzll(lm)))),info->r3,niv,mod));constautoNiv=_mm256_set1_epi32(niv),Mod=_mm256_set1_epi32(mod),Mod2=_mm256_set1_epi32(info->mod2);for(idti=0;i<lm;++i){store256(f+i,convolve8(f+i,g+i,_mm256_set1_epi32(RR),Fx,Niv,Mod,Mod2));RR=mul(RR,info->RT1[__builtin_ctzll(~i)],niv,mod);}}inlinevoidvector_convolution_accumulate(I256*constresult,constI256*constf,constI256*constg,idtlm,constFNTT32_info*constinfo){u32RR=info->one;constautomod=info->mod,niv=info->niv;constautoFx=_mm256_set1_epi32(mul_s((mod-((mod-1)>>(__builtin_ctzll(lm)))),info->r3,niv,mod));constautoNiv=_mm256_set1_epi32(niv),Mod=_mm256_set1_epi32(mod),Mod2=_mm256_set1_epi32(info->mod2);for(idti=0;i<lm;++i){constautoproduct=convolve8(f+i,g+i,_mm256_set1_epi32(RR),Fx,Niv,Mod,Mod2);store256(result+i,add32(load256(result+i),product,Mod2));RR=mul(RR,info->RT1[__builtin_ctzll(~i)],niv,mod);}}}// namespace fast998_v2}// namespace internal}// namespace fps}// namespace m1une#endif // M1UNE_FPS_HAS_X86_SIMD
#line 24 "math/fps/convolution.hpp"
#ifdef M1UNE_FPS_HAS_X86_SIMD
#pragma GCC pop_options
#endif
#line 1 "math/modint.hpp"
#line 6 "math/modint.hpp"
#include<iostream>
#line 9 "math/modint.hpp"
namespacem1une{namespacemath{template<uint32_tModulus>structModInt{static_assert(0<Modulus,"Modulus must be positive");private:uint32_t_v;public:staticconstexpruint32_tmod(){returnModulus;}staticconstexprModIntraw(uint32_tv)noexcept{ModIntx;x._v=v;returnx;}constexprModInt()noexcept:_v(0){}template<classInteger,std::enable_if_t<std::is_integral_v<Integer>,int>=0>constexprModInt(Integerv)noexcept{ifconstexpr(std::is_signed_v<Integer>){int64_tx=static_cast<int64_t>(v)%static_cast<int64_t>(Modulus);if(x<0)x+=Modulus;_v=static_cast<uint32_t>(x);}else{_v=static_cast<uint32_t>(static_cast<uint64_t>(v)%Modulus);}}constexpruint32_tval()constnoexcept{return_v;}constexprModInt&operator++()noexcept{_v++;if(_v==Modulus)_v=0;return*this;}constexprModInt&operator--()noexcept{if(_v==0)_v=Modulus;_v--;return*this;}constexprModIntoperator++(int)noexcept{ModIntres=*this;++*this;returnres;}constexprModIntoperator--(int)noexcept{ModIntres=*this;--*this;returnres;}constexprModInt&operator+=(constModInt&rhs)noexcept{_v+=rhs._v;if(_v>=Modulus)_v-=Modulus;return*this;}constexprModInt&operator-=(constModInt&rhs)noexcept{_v-=rhs._v;if(_v>=Modulus)_v+=Modulus;return*this;}constexprModInt&operator*=(constModInt&rhs)noexcept{uint64_tz=_v;z*=rhs._v;_v=static_cast<uint32_t>(z%Modulus);return*this;}constexprModInt&operator/=(constModInt&rhs)noexcept{return*this*=rhs.inv();}constexprModIntoperator+(constModInt&rhs)constnoexcept{returnModInt(*this)+=rhs;}constexprModIntoperator-(constModInt&rhs)constnoexcept{returnModInt(*this)-=rhs;}constexprModIntoperator*(constModInt&rhs)constnoexcept{returnModInt(*this)*=rhs;}constexprModIntoperator/(constModInt&rhs)constnoexcept{returnModInt(*this)/=rhs;}constexprbooloperator==(constModInt&rhs)constnoexcept{return_v==rhs._v;}constexprbooloperator!=(constModInt&rhs)constnoexcept{return_v!=rhs._v;}constexprModIntpow(longlongn)constnoexcept{ModIntres=raw(1%Modulus);ModIntx=n<0?inv():*this;uint64_texponent=n<0?uint64_t(-(n+1))+1:uint64_t(n);while(exponent>0){if(exponent&1)res*=x;x*=x;exponent>>=1;}returnres;}constexprModIntinv()constnoexcept{int64_ta=_v,b=Modulus,u=1,v=0;while(b){int64_tt=a/b;a-=t*b;std::swap(a,b);u-=t*v;std::swap(u,v);}assert(a==1);u%=Modulus;if(u<0)u+=Modulus;returnraw(static_cast<uint32_t>(u));}friendstd::ostream&operator<<(std::ostream&os,constModInt&rhs){returnos<<rhs._v;}friendstd::istream&operator>>(std::istream&is,ModInt&rhs){longlongv;is>>v;rhs=ModInt(v);returnis;}};usingmodint998244353=ModInt<998244353>;usingmodint1000000007=ModInt<1000000007>;template<intId=0>structDynamicModInt{private:uint32_t_v;inlinestaticuint32_t_mod=1;public:staticuint32_tmod()noexcept{return_mod;}staticvoidset_mod(uint32_tmodulus)noexcept{assert(modulus>0);assert(modulus<=uint32_t(1)<<31);_mod=modulus;}staticDynamicModIntraw(uint32_tv)noexcept{assert(v<_mod);DynamicModIntx;x._v=v;returnx;}DynamicModInt()noexcept:_v(0){}template<classInteger,std::enable_if_t<std::is_integral_v<Integer>,int>=0>DynamicModInt(Integerv)noexcept{ifconstexpr(std::is_signed_v<Integer>){int64_tx=static_cast<int64_t>(v)%static_cast<int64_t>(_mod);if(x<0)x+=_mod;_v=static_cast<uint32_t>(x);}else{_v=static_cast<uint32_t>(static_cast<uint64_t>(v)%_mod);}}uint32_tval()constnoexcept{return_v;}DynamicModInt&operator++()noexcept{_v++;if(_v==_mod)_v=0;return*this;}DynamicModInt&operator--()noexcept{if(_v==0)_v=_mod;_v--;return*this;}DynamicModIntoperator++(int)noexcept{DynamicModIntresult=*this;++*this;returnresult;}DynamicModIntoperator--(int)noexcept{DynamicModIntresult=*this;--*this;returnresult;}DynamicModInt&operator+=(constDynamicModInt&rhs)noexcept{_v+=rhs._v;if(_v>=_mod)_v-=_mod;return*this;}DynamicModInt&operator-=(constDynamicModInt&rhs)noexcept{_v-=rhs._v;if(_v>=_mod)_v+=_mod;return*this;}DynamicModInt&operator*=(constDynamicModInt&rhs)noexcept{_v=static_cast<uint32_t>(uint64_t(_v)*rhs._v%_mod);return*this;}DynamicModInt&operator/=(constDynamicModInt&rhs)noexcept{return*this*=rhs.inv();}DynamicModIntoperator+(constDynamicModInt&rhs)constnoexcept{returnDynamicModInt(*this)+=rhs;}DynamicModIntoperator-(constDynamicModInt&rhs)constnoexcept{returnDynamicModInt(*this)-=rhs;}DynamicModIntoperator*(constDynamicModInt&rhs)constnoexcept{returnDynamicModInt(*this)*=rhs;}DynamicModIntoperator/(constDynamicModInt&rhs)constnoexcept{returnDynamicModInt(*this)/=rhs;}booloperator==(constDynamicModInt&rhs)constnoexcept{return_v==rhs._v;}booloperator!=(constDynamicModInt&rhs)constnoexcept{return_v!=rhs._v;}DynamicModIntpow(longlongexponent)constnoexcept{DynamicModIntresult=raw(1%_mod);DynamicModIntbase=exponent<0?inv():*this;uint64_tmagnitude=exponent<0?uint64_t(-(exponent+1))+1:uint64_t(exponent);while(magnitude>0){if(magnitude&1)result*=base;base*=base;magnitude>>=1;}returnresult;}DynamicModIntinv()constnoexcept{int64_ta=_v,b=_mod,u=1,v=0;while(b){int64_tquotient=a/b;a-=quotient*b;std::swap(a,b);u-=quotient*v;std::swap(u,v);}assert(a==1);u%=_mod;if(u<0)u+=_mod;returnraw(static_cast<uint32_t>(u));}friendstd::ostream&operator<<(std::ostream&os,constDynamicModInt&rhs){returnos<<rhs._v;}friendstd::istream&operator>>(std::istream&is,DynamicModInt&rhs){longlongvalue;is>>value;rhs=DynamicModInt(value);returnis;}};}// namespace math}// namespace m1une#line 29 "math/fps/convolution.hpp"
namespacem1une{namespacefps{namespaceinternal{template<classMint,class=void>structhas_static_modulus:std::false_type{};template<classMint>structhas_static_modulus<Mint,std::void_t<decltype(std::integral_constant<uint32_t,Mint::mod()>{})>>:std::true_type{};constexpruint32_tprimitive_root_constexpr(uint32_tmod){if(mod==2)return1;if(mod==167772161)return3;if(mod==469762049)return3;if(mod==754974721)return11;if(mod==998244353)return3;if(mod==1224736769)return3;uint32_tdivisors[32]={};intcount=0;uint32_tx=mod-1;for(uint32_tp=2;uint64_t(p)*p<=x;p++){if(x%p!=0)continue;divisors[count++]=p;while(x%p==0)x/=p;}if(x>1)divisors[count++]=x;for(uint32_tg=2;;g++){boolok=true;for(inti=0;i<count;i++){uint64_tvalue=1;uint64_tbase=g;uint32_texponent=(mod-1)/divisors[i];while(exponent>0){if(exponent&1)value=value*base%mod;base=base*base%mod;exponent>>=1;}if(value==1){ok=false;break;}}if(ok)returng;}}constexprinttwo_adic_order(uint32_tx){intresult=0;while((x&1)==0){x>>=1;result++;}returnresult;}template<classMint>structNttRoots{staticconstexprintmax_base=two_adic_order(Mint::mod()-1);std::array<Mint,max_base+1>root;std::array<Mint,max_base+1>inverse_root;std::array<Mint,max_base>rate;std::array<Mint,max_base>inverse_rate;std::array<Mint,max_base>rate_radix4;std::array<Mint,max_base>inverse_rate_radix4;NttRoots(){constexpruint32_tprimitive_root=primitive_root_constexpr(Mint::mod());for(intlevel=1;level<=max_base;level++){root[level]=Mint(primitive_root).pow((Mint::mod()-1)>>level);inverse_root[level]=root[level].inv();}Mintproduct=1;Mintinverse_product=1;for(inti=0;i+1<max_base;i++){rate[i]=root[i+2]*product;inverse_rate[i]=inverse_root[i+2]*inverse_product;product*=inverse_root[i+2];inverse_product*=root[i+2];}product=1;inverse_product=1;for(inti=0;i+2<max_base;i++){rate_radix4[i]=root[i+3]*product;inverse_rate_radix4[i]=inverse_root[i+3]*inverse_product;product*=inverse_root[i+3];inverse_product*=root[i+3];}}};template<classMint>constNttRoots<Mint>&ntt_roots(){staticconstNttRoots<Mint>roots;returnroots;}template<classMint>voidntt(std::vector<Mint>&a,boolinverse,boolnormalize=true){constintn=int(a.size());assert(n>0&&(n&(n-1))==0);assert((Mint::mod()-1)%uint32_t(n)==0);constauto&roots=ntt_roots<Mint>();constintheight=two_adic_order(uint32_t(n));if(!inverse){intphase=0;while(phase<height){if(height-phase==1){constintwidth=1<<(height-phase-1);Minttwiddle=1;for(intblock=0;block<(1<<phase);block++){constintoffset=block<<(height-phase);for(inti=0;i<width;i++){constMintleft=a[offset+i];constMintright=a[offset+i+width]*twiddle;a[offset+i]=left+right;a[offset+i+width]=left-right;}if(block+1!=(1<<phase))twiddle*=roots.rate[__builtin_ctz(~uint32_t(block))];}phase++;continue;}constintwidth=1<<(height-phase-2);Minttwiddle=1;constMintimaginary=roots.root[2];for(intblock=0;block<(1<<phase);block++){constMinttwiddle2=twiddle*twiddle;constMinttwiddle3=twiddle2*twiddle;constintoffset=block<<(height-phase);for(inti=0;i<width;i++){constuint64_tmod2=uint64_t(Mint::mod())*Mint::mod();constuint64_ta0=a[offset+i].val();constuint64_ta1=uint64_t(a[offset+i+width].val())*twiddle.val();constuint64_ta2=uint64_t(a[offset+i+2*width].val())*twiddle2.val();constuint64_ta3=uint64_t(a[offset+i+3*width].val())*twiddle3.val();constuint64_ta1na3i=uint64_t(Mint(a1+mod2-a3).val())*imaginary.val();constuint64_tnegative_a2=mod2-a2;a[offset+i]=Mint(a0+a2+a1+a3);a[offset+i+width]=Mint(a0+a2+2*mod2-a1-a3);a[offset+i+2*width]=Mint(a0+negative_a2+a1na3i);a[offset+i+3*width]=Mint(a0+negative_a2+mod2-a1na3i);}if(block+1!=(1<<phase))twiddle*=roots.rate_radix4[__builtin_ctz(~uint32_t(block))];}phase+=2;}}else{intphase=height;while(phase>0){if(phase==1){constintwidth=1<<(height-phase);Minttwiddle=1;for(intblock=0;block<(1<<(phase-1));block++){constintoffset=block<<(height-phase+1);for(inti=0;i<width;i++){constMintleft=a[offset+i];constMintright=a[offset+i+width];a[offset+i]=left+right;a[offset+i+width]=(left-right)*twiddle;}if(block+1!=(1<<(phase-1)))twiddle*=roots.inverse_rate[__builtin_ctz(~uint32_t(block))];}phase--;continue;}constintwidth=1<<(height-phase);Minttwiddle=1;constMintinverse_imaginary=roots.inverse_root[2];for(intblock=0;block<(1<<(phase-2));block++){constMinttwiddle2=twiddle*twiddle;constMinttwiddle3=twiddle2*twiddle;constintoffset=block<<(height-phase+2);for(inti=0;i<width;i++){constuint64_ta0=a[offset+i].val();constuint64_ta1=a[offset+i+width].val();constuint64_ta2=a[offset+i+2*width].val();constuint64_ta3=a[offset+i+3*width].val();constuint64_ta2na3i=uint64_t(Mint((Mint::mod()+a2-a3)*inverse_imaginary.val()).val());a[offset+i]=Mint(a0+a1+a2+a3);a[offset+i+width]=Mint((a0+Mint::mod()-a1+a2na3i)*twiddle.val());a[offset+i+2*width]=Mint((a0+a1+2ULL*Mint::mod()-a2-a3)*twiddle2.val());a[offset+i+3*width]=Mint((a0+Mint::mod()-a1+Mint::mod()-a2na3i)*twiddle3.val());}if(block+1!=(1<<(phase-2)))twiddle*=roots.inverse_rate_radix4[__builtin_ctz(~uint32_t(block))];}phase-=2;}if(normalize){constMintinverse_n=Mint(n).inv();for(Mint&value:a)value*=inverse_n;}}}#ifdef M1UNE_FPS_HAS_X86_SIMD
#pragma GCC push_options
#pragma GCC target("avx2,bmi")
template<classMint>__attribute__((target("avx2,bmi"),hot))std::vector<Mint>convolution_998244353_simd(conststd::vector<Mint>&a,conststd::vector<Mint>&b){constintresult_size=int(a.size()+b.size()-1);intn=1;while(n<result_size)n<<=1;constboolsquaring=&a==&b;auto*transformed_a=static_cast<uint32_t*>(::operatornew[](sizeof(uint32_t)*n,std::align_val_t(32)));auto*transformed_b=squaring?transformed_a:static_cast<uint32_t*>(::operatornew[](sizeof(uint32_t)*n,std::align_val_t(32)));ifconstexpr(std::is_same_v<Mint,math::ModInt<998244353>>){static_assert(sizeof(Mint)==sizeof(uint32_t)&&std::is_trivially_copyable_v<Mint>);std::memcpy(transformed_a,a.data(),sizeof(uint32_t)*a.size());if(!squaring)std::memcpy(transformed_b,b.data(),sizeof(uint32_t)*b.size());}else{for(inti=0;i<int(a.size());i++)transformed_a[i]=a[i].val();if(!squaring)for(inti=0;i<int(b.size());i++)transformed_b[i]=b[i].val();}std::memset(transformed_a+a.size(),0,sizeof(uint32_t)*(n-a.size()));if(!squaring)std::memset(transformed_b+b.size(),0,sizeof(uint32_t)*(n-b.size()));staticconstexprfast998_v2::FNTT32_infotransform(998244353);conststd::size_tvector_size=std::size_t(n)>>3;fast998_v2::vector_dif(reinterpret_cast<__m256i*>(transformed_a),vector_size,&transform);if(!squaring)fast998_v2::vector_dif(reinterpret_cast<__m256i*>(transformed_b),vector_size,&transform);fast998_v2::vector_convolution_direct(reinterpret_cast<__m256i*>(transformed_a),reinterpret_cast<const__m256i*>(transformed_b),vector_size,&transform);fast998_v2::vector_dit<true>(reinterpret_cast<__m256i*>(transformed_a),vector_size,&transform);std::vector<Mint>result(result_size);for(intj=0;j<result_size;j++)result[j]=Mint::raw(transformed_a[j]);::operatordelete[](transformed_a,std::align_val_t(32));if(!squaring)::operatordelete[](transformed_b,std::align_val_t(32));returnresult;}#pragma GCC pop_options
#endif
}// namespace internaltemplate<classMint>std::vector<Mint>convolution_naive(conststd::vector<Mint>&a,conststd::vector<Mint>&b){if(a.empty()||b.empty())return{};std::vector<Mint>result(a.size()+b.size()-1);if(a.size()<b.size()){for(inti=0;i<int(a.size());i++){for(intj=0;j<int(b.size());j++)result[i+j]+=a[i]*b[j];}}else{for(intj=0;j<int(b.size());j++){for(inti=0;i<int(a.size());i++)result[i+j]+=a[i]*b[j];}}returnresult;}template<classMint>std::vector<Mint>convolution_ntt(conststd::vector<Mint>&a,conststd::vector<Mint>&b){constintresult_size=int(a.size()+b.size()-1);intn=1;while(n<result_size)n<<=1;assert((Mint::mod()-1)%uint32_t(n)==0);#ifdef M1UNE_FPS_HAS_X86_SIMD
ifconstexpr(Mint::mod()==998244353){if(n>=64&&__builtin_cpu_supports("avx2"))returninternal::convolution_998244353_simd(a,b);}#endif
// Allocate the padded buffers directly. Constructing from the inputs and// then resizing used to allocate and copy both large operands twice.constboolsquaring=&a==&b;std::vector<Mint>fa(n);std::copy(a.begin(),a.end(),fa.begin());internal::ntt(fa,false);constMintinverse_n=Mint(n).inv();if(squaring){for(inti=0;i<n;i++)fa[i]*=fa[i]*inverse_n;}else{std::vector<Mint>fb(n);std::copy(b.begin(),b.end(),fb.begin());internal::ntt(fb,false);for(inti=0;i<n;i++)fa[i]*=fb[i]*inverse_n;}internal::ntt(fa,true,false);fa.resize(result_size);returnfa;}namespaceinternal{template<classMint>std::vector<Mint>convolution_998244353_blocked_scalar(conststd::vector<Mint>&a,conststd::vector<Mint>&b,inttransform_size){assert(Mint::mod()==998244353);assert(transform_size>=2&&(transform_size&(transform_size-1))==0);assert((Mint::mod()-1)%uint32_t(transform_size)==0);constintblock_size=transform_size/2;constinta_blocks=int((a.size()+block_size-1)/block_size);constintb_blocks=int((b.size()+block_size-1)/block_size);autotransform_blocks=[&](conststd::vector<Mint>&values,intblock_count){std::vector<std::vector<Mint>>blocks;blocks.reserve(block_count);for(intblock=0;block<block_count;block++){constintbegin=block*block_size;constintcount=std::min(block_size,int(values.size())-begin);std::vector<Mint>transformed(transform_size);std::copy_n(values.begin()+begin,count,transformed.begin());ntt(transformed,false);blocks.emplace_back(std::move(transformed));}returnblocks;};std::vector<std::vector<Mint>>transformed_a=transform_blocks(a,a_blocks);std::vector<std::vector<Mint>>transformed_b=transform_blocks(b,b_blocks);constintresult_size=int(a.size()+b.size()-1);std::vector<Mint>result(result_size);std::vector<Mint>transformed_result(transform_size);for(intdiagonal=0;diagonal<a_blocks+b_blocks-1;diagonal++){std::fill(transformed_result.begin(),transformed_result.end(),Mint(0));constintfirst_a=std::max(0,diagonal-(b_blocks-1));constintlast_a=std::min(a_blocks-1,diagonal);for(inta_block=first_a;a_block<=last_a;a_block++){constintb_block=diagonal-a_block;for(inti=0;i<transform_size;i++)transformed_result[i]+=transformed_a[a_block][i]*transformed_b[b_block][i];}ntt(transformed_result,true);constintoutput_offset=diagonal*block_size;constintoutput_count=std::min(transform_size,result_size-output_offset);for(inti=0;i<output_count;i++)result[output_offset+i]+=transformed_result[i];}returnresult;}#ifdef M1UNE_FPS_HAS_X86_SIMD
classAlignedUint32Buffer{private:uint32_t*data_;public:explicitAlignedUint32Buffer(std::size_tsize):data_(static_cast<uint32_t*>(::operatornew[](sizeof(uint32_t)*size,std::align_val_t(32)))){}AlignedUint32Buffer(constAlignedUint32Buffer&)=delete;AlignedUint32Buffer&operator=(constAlignedUint32Buffer&)=delete;AlignedUint32Buffer(AlignedUint32Buffer&&other)noexcept:data_(other.data_){other.data_=nullptr;}AlignedUint32Buffer&operator=(AlignedUint32Buffer&&other)noexcept{if(this==&other)return*this;::operatordelete[](data_,std::align_val_t(32));data_=other.data_;other.data_=nullptr;return*this;}~AlignedUint32Buffer(){::operatordelete[](data_,std::align_val_t(32));}uint32_t*data(){returndata_;}constuint32_t*data()const{returndata_;}};template<classMint>__attribute__((target("avx2,bmi"),hot))std::vector<Mint>convolution_998244353_blocked_simd(conststd::vector<Mint>&a,conststd::vector<Mint>&b,inttransform_size){assert(Mint::mod()==998244353);assert(transform_size>=64&&(transform_size&(transform_size-1))==0);assert((Mint::mod()-1)%uint32_t(transform_size)==0);constintblock_size=transform_size/2;constinta_blocks=int((a.size()+block_size-1)/block_size);constintb_blocks=int((b.size()+block_size-1)/block_size);staticconstexprfast998_v2::FNTT32_infotransform(998244353);conststd::size_tvector_size=std::size_t(transform_size)/8;autotransform_blocks=[&](conststd::vector<Mint>&values,intblock_count){std::vector<AlignedUint32Buffer>blocks;blocks.reserve(block_count);for(intblock=0;block<block_count;block++){constintbegin=block*block_size;constintcount=std::min(block_size,int(values.size())-begin);AlignedUint32Buffertransformed(transform_size);ifconstexpr(std::is_same_v<Mint,math::ModInt<998244353>>){static_assert(sizeof(Mint)==sizeof(uint32_t)&&std::is_trivially_copyable_v<Mint>);std::memcpy(transformed.data(),values.data()+begin,sizeof(uint32_t)*count);}else{for(inti=0;i<count;i++)transformed.data()[i]=values[begin+i].val();}std::memset(transformed.data()+count,0,sizeof(uint32_t)*(transform_size-count));fast998_v2::vector_dif(reinterpret_cast<__m256i*>(transformed.data()),vector_size,&transform);blocks.emplace_back(std::move(transformed));}returnblocks;};std::vector<AlignedUint32Buffer>transformed_a=transform_blocks(a,a_blocks);std::vector<AlignedUint32Buffer>transformed_b=transform_blocks(b,b_blocks);constintresult_size=int(a.size()+b.size()-1);std::vector<Mint>result(result_size);AlignedUint32Buffertransformed_result(transform_size);for(intdiagonal=0;diagonal<a_blocks+b_blocks-1;diagonal++){std::memset(transformed_result.data(),0,sizeof(uint32_t)*transform_size);constintfirst_a=std::max(0,diagonal-(b_blocks-1));constintlast_a=std::min(a_blocks-1,diagonal);for(inta_block=first_a;a_block<=last_a;a_block++){constintb_block=diagonal-a_block;fast998_v2::vector_convolution_accumulate(reinterpret_cast<__m256i*>(transformed_result.data()),reinterpret_cast<const__m256i*>(transformed_a[a_block].data()),reinterpret_cast<const__m256i*>(transformed_b[b_block].data()),vector_size,&transform);}fast998_v2::vector_dit<true>(reinterpret_cast<__m256i*>(transformed_result.data()),vector_size,&transform);constintoutput_offset=diagonal*block_size;constintoutput_count=std::min(transform_size,result_size-output_offset);for(inti=0;i<output_count;i++){uint32_tvalue=result[output_offset+i].val()+transformed_result.data()[i];if(value>=Mint::mod())value-=Mint::mod();result[output_offset+i]=Mint::raw(value);}}returnresult;}#endif
template<classMint>std::vector<Mint>convolution_998244353_blocked(conststd::vector<Mint>&a,conststd::vector<Mint>&b,inttransform_size=1<<23){#ifdef M1UNE_FPS_HAS_X86_SIMD
if(transform_size>=64&&__builtin_cpu_supports("avx2"))returnconvolution_998244353_blocked_simd(a,b,transform_size);#endif
returnconvolution_998244353_blocked_scalar(a,b,transform_size);}}// namespace internaltemplate<classMint>std::vector<Mint>convolution(conststd::vector<Mint>&a,conststd::vector<Mint>&b){if(a.empty()||b.empty())return{};if(std::min(a.size(),b.size())<=32)returnconvolution_naive(a,b);constintresult_size=int(a.size()+b.size()-1);intn=1;while(n<result_size)n<<=1;ifconstexpr(internal::has_static_modulus<Mint>::value){ifconstexpr(Mint::mod()==998244353){if(n>(1<<23))returninternal::convolution_998244353_blocked(a,b);}if((Mint::mod()-1)%uint32_t(n)==0)returnconvolution_ntt(a,b);}usingMint1=math::ModInt<167772161>;usingMint2=math::ModInt<469762049>;usingMint3=math::ModInt<754974721>;assert(n<=(1<<24));[[maybe_unused]]constunsigned__int128coefficient_bound=static_cast<unsigned__int128>(std::min(a.size(),b.size()))*(Mint::mod()-1)*(Mint::mod()-1);[[maybe_unused]]constunsigned__int128crt_modulus=static_cast<unsigned__int128>(Mint1::mod())*Mint2::mod()*Mint3::mod();assert(coefficient_bound<crt_modulus);autoconverted_convolution=[&]<classOtherMint>(){std::vector<OtherMint>converted_a(a.size());std::vector<OtherMint>converted_b(b.size());for(inti=0;i<int(a.size());i++)converted_a[i]=OtherMint(a[i].val());for(inti=0;i<int(b.size());i++)converted_b[i]=OtherMint(b[i].val());returnconvolution_ntt(converted_a,converted_b);};std::vector<Mint1>c1=converted_convolution.templateoperator()<Mint1>();std::vector<Mint2>c2=converted_convolution.templateoperator()<Mint2>();std::vector<Mint3>c3=converted_convolution.templateoperator()<Mint3>();staticconstuint64_tinverse_mod1_mod2=Mint2(Mint1::mod()).inv().val();staticconstuint64_tmod1_mod3=Mint1::mod()%Mint3::mod();staticconstuint64_tmod1_mod2_mod3=mod1_mod3*(Mint2::mod()%Mint3::mod())%Mint3::mod();staticconstuint64_tinverse_mod1_mod2_mod3=Mint3(uint32_t(mod1_mod2_mod3)).inv().val();constuint64_ttarget_mod=Mint::mod();constuint64_tmod1_target=Mint1::mod()%target_mod;constuint64_tmod1_mod2_target=mod1_target*(Mint2::mod()%target_mod)%target_mod;std::vector<Mint>result(result_size);for(inti=0;i<result_size;i++){constuint64_tr1=c1[i].val();constuint64_tr2=c2[i].val();constuint64_tr3=c3[i].val();constuint64_tfirst=(r2+Mint2::mod()-r1%Mint2::mod())%Mint2::mod()*inverse_mod1_mod2%Mint2::mod();constuint64_tcombined_mod3=(r1%Mint3::mod()+mod1_mod3*(first%Mint3::mod()))%Mint3::mod();constuint64_tsecond=(r3+Mint3::mod()-combined_mod3)%Mint3::mod()*inverse_mod1_mod2_mod3%Mint3::mod();uint64_tvalue=r1%target_mod;value=(value+mod1_target*(first%target_mod))%target_mod;value=(value+mod1_mod2_target*(second%target_mod))%target_mod;result[i]=Mint::raw(uint32_t(value));}returnresult;}}// namespace fps}// namespace m1une#ifdef M1UNE_FPS_HAS_X86_SIMD
#undef M1UNE_FPS_HAS_X86_SIMD
#endif
#line 1 "math/fps/formal_power_series.hpp"
#line 10 "math/fps/formal_power_series.hpp"
#line 1 "math/modular_square_root.hpp"
#line 7 "math/modular_square_root.hpp"
namespacem1une{namespacemath{namespaceinternal{inlineuint64_tmodular_square_root_multiply(uint64_tlhs,uint64_trhs,uint64_tmod){returnstatic_cast<uint64_t>(static_cast<unsigned__int128>(lhs)*rhs%mod);}inlineuint64_tmodular_square_root_power(uint64_tbase,uint64_texponent,uint64_tmod){uint64_tresult=1%mod;while(exponent>0){if(exponent&1)result=modular_square_root_multiply(result,base,mod);base=modular_square_root_multiply(base,base,mod);exponent>>=1;}returnresult;}}// namespace internal// Returns x such that x * x = value (mod prime), or nullopt when no such x exists.// The modulus must be prime.inlinestd::optional<uint64_t>modular_square_root(uint64_tvalue,uint64_tprime){assert(prime>=2);value%=prime;if(value==0||prime==2)returnvalue;if(internal::modular_square_root_power(value,(prime-1)/2,prime)!=1){returnstd::nullopt;}if(prime%4==3){returninternal::modular_square_root_power(value,prime/4+1,prime);}uint64_todd_part=prime-1;intpower_of_two=0;while((odd_part&1)==0){odd_part>>=1;power_of_two++;}uint64_tnon_residue=2;while(internal::modular_square_root_power(non_residue,(prime-1)/2,prime)==1){non_residue++;}uint64_tc=internal::modular_square_root_power(non_residue,odd_part,prime);uint64_troot=internal::modular_square_root_power(value,odd_part/2+1,prime);uint64_tremainder=internal::modular_square_root_power(value,odd_part,prime);intremaining_power=power_of_two;while(remainder!=1){intexponent=1;uint64_tsquared=internal::modular_square_root_multiply(remainder,remainder,prime);while(squared!=1){squared=internal::modular_square_root_multiply(squared,squared,prime);exponent++;}uint64_tcorrection=c;for(inti=0;i<remaining_power-exponent-1;i++){correction=internal::modular_square_root_multiply(correction,correction,prime);}root=internal::modular_square_root_multiply(root,correction,prime);c=internal::modular_square_root_multiply(correction,correction,prime);remainder=internal::modular_square_root_multiply(remainder,c,prime);remaining_power=exponent;}returnroot;}template<classMint>std::optional<Mint>modular_square_root(Mintvalue){autoroot=modular_square_root(static_cast<uint64_t>(value.val()),static_cast<uint64_t>(Mint::mod()));if(!root.has_value())returnstd::nullopt;returnMint(*root);}}// namespace math}// namespace m1une#line 13 "math/fps/formal_power_series.hpp"
namespacem1une{namespacefps{template<classMint>structFormalPowerSeries:std::vector<Mint>{usingstd::vector<Mint>::vector;usingFps=FormalPowerSeries;FormalPowerSeries()=default;FormalPowerSeries(conststd::vector<Mint>&values):std::vector<Mint>(values){}FormalPowerSeries(std::vector<Mint>&&values):std::vector<Mint>(std::move(values)){}Fps&shrink(){while(!this->empty()&&this->back()==Mint(0))this->pop_back();return*this;}Fpspre(intdegree)const{assert(degree>=0);Fpsresult(this->begin(),this->begin()+std::min<int>(degree,this->size()));result.resize(degree);returnresult;}Fpsreversed(intsize=-1)const{Fpsresult=*this;if(size>=0)result.resize(size);std::reverse(result.begin(),result.end());returnresult;}Fps&operator+=(constFps&rhs){if(this->size()<rhs.size())this->resize(rhs.size());for(inti=0;i<int(rhs.size());i++)(*this)[i]+=rhs[i];return*this;}Fps&operator-=(constFps&rhs){if(this->size()<rhs.size())this->resize(rhs.size());for(inti=0;i<int(rhs.size());i++)(*this)[i]-=rhs[i];return*this;}Fps&operator*=(constFps&rhs){std::vector<Mint>lhs(this->begin(),this->end());*this=convolution(lhs,rhs);return*this;}Fps&operator*=(Mintrhs){for(Mint&value:*this)value*=rhs;return*this;}Fps&operator/=(Mintrhs){return*this*=rhs.inv();}Fps&operator<<=(intshift){assert(shift>=0);this->insert(this->begin(),shift,Mint(0));return*this;}Fps&operator>>=(intshift){assert(shift>=0);if(shift>=int(this->size())){this->clear();}else{this->erase(this->begin(),this->begin()+shift);}return*this;}Fpsoperator+()const{return*this;}Fpsoperator-()const{Fpsresult=*this;for(Mint&value:result)value=Mint(0)-value;returnresult;}friendFpsoperator+(Fpslhs,constFps&rhs){returnlhs+=rhs;}friendFpsoperator-(Fpslhs,constFps&rhs){returnlhs-=rhs;}friendFpsoperator*(Fpslhs,constFps&rhs){returnlhs*=rhs;}friendFpsoperator*(Fpslhs,Mintrhs){returnlhs*=rhs;}friendFpsoperator*(Mintlhs,Fpsrhs){returnrhs*=lhs;}friendFpsoperator/(Fpslhs,Mintrhs){returnlhs/=rhs;}friendFpsoperator<<(Fpslhs,intshift){returnlhs<<=shift;}friendFpsoperator>>(Fpslhs,intshift){returnlhs>>=shift;}Fpsderivative()const{if(this->empty())return{};Fpsresult(this->size()-1);for(inti=1;i<int(this->size());i++)result[i-1]=(*this)[i]*Mint(i);returnresult;}Fpsintegral()const{Fpsresult(this->size()+1);if(this->empty())returnresult;assert(this->size()<Mint::mod());std::vector<Mint>inverse(this->size()+1);inverse[1]=1;for(inti=2;i<=int(this->size());i++){inverse[i]=Mint(0)-Mint(Mint::mod()/uint32_t(i))*inverse[Mint::mod()%uint32_t(i)];}for(inti=0;i<int(this->size());i++)result[i+1]=(*this)[i]*inverse[i+1];returnresult;}Mintevaluate(Mintx)const{Mintresult=0;for(autoit=this->rbegin();it!=this->rend();++it)result=result*x+*it;returnresult;}Fpsinv(intdegree=-1)const{if(degree<0)degree=int(this->size());assert(degree>=0);if(degree==0)return{};assert(!this->empty()&&(*this)[0]!=Mint(0));Fpsresult(1,(*this)[0].inv());for(intsize=1;size<degree;size<<=1){constintnext_size=std::min(size<<1,degree);constinttransform_size=size<<1;if(size>=32&&(Mint::mod()-1)%uint32_t(transform_size)==0){// Newton's g <- g(2-fg), restricted to the newly determined// half. Keeping g in the frequency domain avoids two general// convolutions and their 2x larger padding.std::vector<Mint>transformed_f(transform_size);std::copy_n(this->begin(),std::min<int>(this->size(),next_size),transformed_f.begin());std::vector<Mint>transformed_g(transform_size);std::copy(result.begin(),result.end(),transformed_g.begin());internal::ntt(transformed_f,false);internal::ntt(transformed_g,false);std::vector<Mint>error(transform_size);for(inti=0;i<transform_size;i++)error[i]=transformed_f[i]*transformed_g[i];internal::ntt(error,true);std::fill(error.begin(),error.begin()+size,Mint(0));internal::ntt(error,false);for(inti=0;i<transform_size;i++)error[i]*=transformed_g[i];internal::ntt(error,true);result.resize(next_size);for(inti=size;i<next_size;i++)result[i]=Mint(0)-error[i];continue;}Fpsproduct=this->pre(next_size)*result;product.resize(next_size);for(Mint&value:product)value=Mint(0)-value;product[0]+=Mint(2);result=(result*product).pre(next_size);}returnresult.pre(degree);}Fpslog(intdegree=-1)const{if(degree<0)degree=int(this->size());assert(degree>=0);if(degree==0)return{};assert(!this->empty()&&(*this)[0]==Mint(1));return(derivative()*inv(degree)).pre(degree-1).integral();}Fpsexp(intdegree=-1)const{if(degree<0)degree=int(this->size());assert(degree>=0);if(degree==0)return{};assert(this->empty()||(*this)[0]==Mint(0));Fpsresult(1,Mint(1));for(intsize=1;size<degree;size<<=1){constintnext_size=std::min(size<<1,degree);Fpscorrection=this->pre(next_size)-result.log(next_size);correction[0]+=Mint(1);result=(result*correction).pre(next_size);}returnresult.pre(degree);}Fpspow(longlongexponent,intdegree=-1)const{if(degree<0)degree=int(this->size());assert(exponent>=0&°ree>=0);if(degree==0)return{};if(exponent==0){Fpsresult(degree);result[0]=1;returnresult;}intfirst=0;while(first<int(this->size())&&(*this)[first]==Mint(0))first++;if(first==int(this->size())||first>(degree-1)/exponent)returnFps(degree);constintshift=int(first*exponent);constMintleading=(*this)[first];Fpsnormalized=(*this>>first)/leading;Fpsresult=(normalized.log(degree-shift)*Mint(exponent)).exp(degree-shift);result*=leading.pow(exponent);result<<=shift;result.resize(degree);returnresult;}std::optional<Fps>sqrt(intdegree=-1)const{if(degree<0)degree=int(this->size());assert(degree>=0);if(degree==0)returnFps();intfirst=0;while(first<int(this->size())&&(*this)[first]==Mint(0))first++;if(first==int(this->size()))returnFps(degree);if(first>=degree)returnFps(degree);if(first&1)returnstd::nullopt;constintshift=first/2;autoleading_root=m1une::math::modular_square_root((*this)[first]);if(!leading_root.has_value())returnstd::nullopt;constintresult_degree=degree-shift;Fpsnormalized=(*this>>first)/(*this)[first];Fpsresult=(normalized.log(result_degree)/Mint(2)).exp(result_degree);result*=*leading_root;result<<=shift;result.resize(degree);returnresult;}std::pair<Fps,Fps>divmod(constFps&divisor)const{Fpsdividend=*this;Fpsnormalized_divisor=divisor;dividend.shrink();normalized_divisor.shrink();assert(!normalized_divisor.empty());if(dividend.size()<normalized_divisor.size())returnstd::make_pair(Fps(),dividend);constintquotient_size=int(dividend.size()-normalized_divisor.size()+1);Fpsquotient=(dividend.reversed().pre(quotient_size)*normalized_divisor.reversed().inv(quotient_size)).pre(quotient_size).reversed();quotient.shrink();Fpsremainder=dividend-normalized_divisor*quotient;remainder.resize(normalized_divisor.size()-1);remainder.shrink();returnstd::make_pair(std::move(quotient),std::move(remainder));}Fps&operator/=(constFps&rhs){*this=divmod(rhs).first;return*this;}Fps&operator%=(constFps&rhs){*this=divmod(rhs).second;return*this;}friendFpsoperator/(Fpslhs,constFps&rhs){returnlhs/=rhs;}friendFpsoperator%(Fpslhs,constFps&rhs){returnlhs%=rhs;}Fpstaylor_shift(Mintshift)const{constintn=int(this->size());if(n==0)return{};assert(uint32_t(n)<Mint::mod());std::vector<Mint>factorial(n,Mint(1));std::vector<Mint>inverse_factorial(n,Mint(1));for(inti=1;i<n;i++)factorial[i]=factorial[i-1]*Mint(i);inverse_factorial[n-1]=factorial[n-1].inv();for(inti=n-1;i>0;i--)inverse_factorial[i-1]=inverse_factorial[i]*Mint(i);Fpsleft(n);Fpsright(n);Mintpower=1;for(inti=0;i<n;i++){left[n-1-i]=(*this)[i]*factorial[i];right[i]=power*inverse_factorial[i];power*=shift;}Fpsproduct=left*right;Fpsresult(n);for(inti=0;i<n;i++)result[i]=product[n-1-i]*inverse_factorial[i];returnresult;}};}// namespace fps}// namespace m1une#line 1 "math/combinatorics.hpp"
#line 7 "math/combinatorics.hpp"
namespacem1une{namespacemath{template<classMint>structCombinatorics{private:std::vector<Mint>_factorial;std::vector<Mint>_inverse_factorial;public:explicitCombinatorics(intmaximum=0):_factorial(1,Mint(1)),_inverse_factorial(1,Mint(1)){ensure(maximum);}intmaximum()const{returnint(_factorial.size())-1;}voidensure(intmaximum){assert(maximum>=0);assert(static_cast<uint64_t>(maximum)<Mint::mod());if(maximum<=this->maximum())return;constintold_maximum=this->maximum();_factorial.resize(maximum+1);_inverse_factorial.resize(maximum+1);for(inti=old_maximum+1;i<=maximum;i++){_factorial[i]=_factorial[i-1]*Mint(i);}_inverse_factorial[maximum]=_factorial[maximum].inv();for(inti=maximum;i>old_maximum;i--){_inverse_factorial[i-1]=_inverse_factorial[i]*Mint(i);}}Mintfactorial(intn)const{assert(0<=n&&n<=maximum());return_factorial[n];}Mintinverse_factorial(intn)const{assert(0<=n&&n<=maximum());return_inverse_factorial[n];}Mintinverse(intn)const{assert(1<=n&&n<=maximum());return_factorial[n-1]*_inverse_factorial[n];}Mintbinom(intn,intk)const{if(k<0||k>n)returnMint(0);assert(n<=maximum());return_factorial[n]*_inverse_factorial[k]*_inverse_factorial[n-k];}Mintperm(intn,intk)const{if(k<0||k>n)returnMint(0);assert(n<=maximum());return_factorial[n]*_inverse_factorial[n-k];}Mintmultiset(inttypes,intcount)const{if(types<0||count<0)returnMint(0);if(types==0)returnMint(count==0);constlonglongtotal=static_cast<longlong>(types)+count-1;assert(total<=maximum());returnbinom(static_cast<int>(total),count);}Mintcatalan(intn)const{assert(n>=0);constlonglongdoubled=2LL*n;assert(doubled<=maximum());returnbinom(int(doubled),n)-binom(int(doubled),n+1);}};}// namespace math}// namespace m1une#line 13 "graph/counting.hpp"
namespacem1une{namespacegraph{namespacegraph_counting_detail{template<classMint>usingFps=fps::FormalPowerSeries<Mint>;template<classMint>voidassert_maximum(intmaximum){assert(maximum>=0);assert(static_cast<uint64_t>(maximum)<Mint::mod());}template<classMint>Mintinverse_two(){assert(Mint::mod()!=2);returnMint(2).inv();}template<classMint>std::vector<Mint>to_egf(std::vector<Mint>values,constmath::Combinatorics<Mint>&combinations){for(inti=0;i<int(values.size());i++){values[i]*=combinations.inverse_factorial(i);}returnvalues;}template<classMint>std::vector<Mint>from_egf(std::vector<Mint>coefficients,constmath::Combinatorics<Mint>&combinations){for(inti=0;i<int(coefficients.size());i++){coefficients[i]*=combinations.factorial(i);}returncoefficients;}template<classMint>std::vector<Mint>two_to_binom2(intmaximum){std::vector<Mint>result(maximum+1);result[0]=1;Mintmultiplier=1;for(intn=1;n<=maximum;n++){result[n]=result[n-1]*multiplier;multiplier+=multiplier;}returnresult;}template<classMint>Fps<Mint>colored_bipartite_egf(intmaximum,constmath::Combinatorics<Mint>&combinations){constMinthalf=inverse_two<Mint>();Fps<Mint>kernel(maximum+1);kernel[0]=1;Mintmultiplier=1;for(inti=1;i<=maximum;i++){kernel[i]=kernel[i-1]*multiplier;multiplier*=half;}for(inti=0;i<=maximum;i++){kernel[i]*=combinations.inverse_factorial(i);}Fps<Mint>result=(kernel*kernel).pre(maximum+1);std::vector<Mint>edge_powers=two_to_binom2<Mint>(maximum);for(inti=0;i<=maximum;i++)result[i]*=edge_powers[i];returnresult;}}// namespace graph_counting_detailtemplate<classMint>std::vector<Mint>count_labeled_undirected_graphs(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);returngraph_counting_detail::two_to_binom2<Mint>(maximum);}template<classMint>std::vector<Mint>count_labeled_connected_graphs(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);math::Combinatorics<Mint>combinations(maximum);graph_counting_detail::Fps<Mint>egf=graph_counting_detail::to_egf(count_labeled_undirected_graphs<Mint>(maximum),combinations);egf=egf.log(maximum+1);returngraph_counting_detail::from_egf(std::move(egf),combinations);}template<classMint>std::vector<Mint>count_labeled_trees(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);std::vector<Mint>result(maximum+1);for(intn=1;n<=maximum;n++){result[n]=(n==1?Mint(1):Mint(n).pow(n-2));}returnresult;}template<classMint>std::vector<Mint>count_labeled_forests(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);math::Combinatorics<Mint>combinations(maximum);graph_counting_detail::Fps<Mint>egf=graph_counting_detail::to_egf(count_labeled_trees<Mint>(maximum),combinations);egf=egf.exp(maximum+1);returngraph_counting_detail::from_egf(std::move(egf),combinations);}template<classMint>std::vector<Mint>count_labeled_unicyclic_connected_graphs(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);math::Combinatorics<Mint>combinations(maximum);usingFps=graph_counting_detail::Fps<Mint>;Fpsrooted_tree_egf(maximum+1);for(intn=1;n<=maximum;n++){rooted_tree_egf[n]=Mint(n).pow(n-1)*combinations.inverse_factorial(n);}Fpsone_minus_rooted(maximum+1);one_minus_rooted[0]=1;for(inti=1;i<=maximum;i++){one_minus_rooted[i]=Mint(0)-rooted_tree_egf[i];}Fpsegf=one_minus_rooted.log(maximum+1);for(Mint&coefficient:egf)coefficient=Mint(0)-coefficient;egf-=rooted_tree_egf;egf-=((rooted_tree_egf*rooted_tree_egf).pre(maximum+1)*graph_counting_detail::inverse_two<Mint>());egf*=graph_counting_detail::inverse_two<Mint>();returngraph_counting_detail::from_egf(std::move(egf),combinations);}template<classMint>std::vector<Mint>count_labeled_connected_eulerian_graphs(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);math::Combinatorics<Mint>combinations(maximum);std::vector<Mint>all_even(maximum+1);all_even[0]=1;if(maximum>=1){std::vector<Mint>shifted=count_labeled_undirected_graphs<Mint>(maximum-1);for(intn=1;n<=maximum;n++)all_even[n]=shifted[n-1];}graph_counting_detail::Fps<Mint>egf=graph_counting_detail::to_egf(std::move(all_even),combinations);egf=egf.log(maximum+1);returngraph_counting_detail::from_egf(std::move(egf),combinations);}template<classMint>std::vector<Mint>count_labeled_connected_bipartite_graphs(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);math::Combinatorics<Mint>combinations(maximum);graph_counting_detail::Fps<Mint>egf=graph_counting_detail::colored_bipartite_egf(maximum,combinations).log(maximum+1);egf*=graph_counting_detail::inverse_two<Mint>();returngraph_counting_detail::from_egf(std::move(egf),combinations);}template<classMint>std::vector<Mint>count_labeled_bipartite_graphs(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);math::Combinatorics<Mint>combinations(maximum);std::optional<graph_counting_detail::Fps<Mint>>egf=graph_counting_detail::colored_bipartite_egf(maximum,combinations).sqrt(maximum+1);assert(egf.has_value());returngraph_counting_detail::from_egf(std::move(*egf),combinations);}template<classMint>std::vector<Mint>count_labeled_directed_graphs(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);std::vector<Mint>result(maximum+1);result[0]=1;Mintmultiplier=1;constMintfour=4;for(intn=1;n<=maximum;n++){result[n]=result[n-1]*multiplier;multiplier*=four;}returnresult;}template<classMint>std::vector<Mint>count_labeled_dags(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);math::Combinatorics<Mint>combinations(maximum);usingFps=graph_counting_detail::Fps<Mint>;Fpsdenominator(maximum+1);Mintmultiplier=1;constMinthalf=graph_counting_detail::inverse_two<Mint>();denominator[0]=1;for(intn=1;n<=maximum;n++){denominator[n]=denominator[n-1]*multiplier;multiplier*=half;}for(intn=0;n<=maximum;n++){denominator[n]*=combinations.inverse_factorial(n);if(n&1)denominator[n]=Mint(0)-denominator[n];}Fpsegf=denominator.inv(maximum+1);std::vector<Mint>edge_powers=graph_counting_detail::two_to_binom2<Mint>(maximum);for(intn=0;n<=maximum;n++){egf[n]*=combinations.factorial(n)*edge_powers[n];}returnegf;}template<classMint>std::vector<Mint>count_labeled_strongly_connected_digraphs(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);math::Combinatorics<Mint>combinations(maximum);graph_counting_detail::Fps<Mint>egf(maximum+1);std::vector<Mint>edge_powers=graph_counting_detail::two_to_binom2<Mint>(maximum);for(intn=0;n<=maximum;n++){egf[n]=edge_powers[n]*combinations.inverse_factorial(n);}egf=egf.inv(maximum+1);for(intn=0;n<=maximum;n++)egf[n]*=edge_powers[n];egf=egf.log(maximum+1);for(intn=0;n<=maximum;n++){egf[n]=Mint(0)-egf[n]*combinations.factorial(n);}returnegf;}template<classMint>std::vector<Mint>count_labeled_tournaments(intmaximum){returncount_labeled_undirected_graphs<Mint>(maximum);}template<classMint>std::vector<Mint>count_labeled_strongly_connected_tournaments(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);math::Combinatorics<Mint>combinations(maximum);graph_counting_detail::Fps<Mint>egf=graph_counting_detail::to_egf(count_labeled_tournaments<Mint>(maximum),combinations);egf=egf.inv(maximum+1);if(!egf.empty())egf[0]=0;for(intn=0;n<=maximum;n++){egf[n]=Mint(0)-egf[n]*combinations.factorial(n);}returnegf;}template<classMint>std::vector<Mint>count_unlabeled_rooted_trees(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);std::vector<Mint>result(maximum+1);if(maximum==0)returnresult;std::vector<Mint>divisor_sum(maximum+1);result[1]=1;for(intmultiple=1;multiple<=maximum;multiple++){divisor_sum[multiple]+=result[1];}for(intn=1;n<maximum;n++){Mintsum=0;for(inti=1;i<=n;i++){sum+=divisor_sum[i]*result[n-i+1];}result[n+1]=sum/Mint(n);constintsize=n+1;constMintcontribution=Mint(size)*result[size];for(intmultiple=size;multiple<=maximum;multiple+=size){divisor_sum[multiple]+=contribution;}}returnresult;}template<classMint>std::vector<Mint>count_unlabeled_trees(intmaximum){graph_counting_detail::assert_maximum<Mint>(maximum);usingFps=graph_counting_detail::Fps<Mint>;Fpsrooted=count_unlabeled_rooted_trees<Mint>(maximum);Fpsrooted_square=(rooted*rooted).pre(maximum+1);constMinthalf=graph_counting_detail::inverse_two<Mint>();std::vector<Mint>result(maximum+1);for(intn=1;n<=maximum;n++){result[n]=rooted[n]-rooted_square[n]*half;if((n&1)==0)result[n]+=rooted[n/2]*half;}returnresult;}}// namespace graph}// namespace m1une#line 1 "graph/directed.hpp"
#line 1 "graph/cycle_detection.hpp"
#line 7 "graph/cycle_detection.hpp"
#line 1 "graph/graph.hpp"
#line 8 "graph/graph.hpp"
namespacem1une{namespacegraph{template<classT=int>structEdge{usingcost_type=T;intfrom;intto;Tcost;intid;boolalive;Edge():from(-1),to(-1),cost(T()),id(-1),alive(true){}Edge(intfrom_,intto_,Tcost_=T(1),intid_=-1,boolalive_=true):from(from_),to(to_),cost(cost_),id(id_),alive(alive_){}intother(intv)const{assert(v==from||v==to);returnfrom^to^v;}};template<classT=int>structGraph{usingedge_type=Edge<T>;usingcost_type=T;private:structEdgePositions{std::array<std::pair<int,int>,2>value{};intsize=0;voidpush_back(std::pair<int,int>position){assert(size<2);value[size++]=position;}};int_n;int_edge_count;std::vector<std::vector<edge_type>>_g;std::vector<EdgePositions>_edge_positions;public:Graph():_n(0),_edge_count(0){}explicitGraph(intn):_n(n),_edge_count(0),_g(n){assert(0<=n);}intsize()const{return_n;}boolempty()const{return_n==0;}intedge_count()const{return_edge_count;}intadd_vertex(){_g.emplace_back();return_n++;}intadd_directed_edge(intfrom,intto,Tcost=T(1)){assert(0<=from&&from<_n);assert(0<=to&&to<_n);intid=_edge_count++;intidx=int(_g[from].size());_g[from].push_back(edge_type(from,to,cost,id));_edge_positions.emplace_back();_edge_positions.back().push_back({from,idx});returnid;}intadd_edge(intu,intv,Tcost=T(1)){assert(0<=u&&u<_n);assert(0<=v&&v<_n);intid=_edge_count++;intu_idx=int(_g[u].size());_g[u].push_back(edge_type(u,v,cost,id));intv_idx=int(_g[v].size());_g[v].push_back(edge_type(v,u,cost,id));_edge_positions.emplace_back();_edge_positions.back().push_back({u,u_idx});_edge_positions.back().push_back({v,v_idx});returnid;}voidset_edge_alive(intid,boolalive){assert(0<=id&&id<_edge_count);for(inti=0;i<_edge_positions[id].size;++i){auto[v,idx]=_edge_positions[id].value[i];_g[v][idx].alive=alive;}}voiderase_edge(intid){set_edge_alive(id,false);}voidrevive_edge(intid){set_edge_alive(id,true);}boolis_edge_alive(intid)const{assert(0<=id&&id<_edge_count);assert(_edge_positions[id].size!=0);auto[v,idx]=_edge_positions[id].value[0];return_g[v][idx].alive;}conststd::vector<edge_type>&operator[](intv)const{assert(0<=v&&v<_n);return_g[v];}std::vector<edge_type>&operator[](intv){assert(0<=v&&v<_n);return_g[v];}conststd::vector<std::vector<edge_type>>&adjacency()const{return_g;}std::vector<std::vector<edge_type>>&adjacency(){return_g;}std::vector<edge_type>edges(boolinclude_inactive=false)const{std::vector<edge_type>result;result.reserve(_edge_count);std::vector<char>used(_edge_count,false);for(intv=0;v<_n;v++){for(constauto&e:_g[v]){if(!include_inactive&&!e.alive)continue;if(0<=e.id&&e.id<_edge_count){if(used[e.id])continue;used[e.id]=true;}result.push_back(e);}}returnresult;}Graphreversed()const{Graphresult(_n);result._edge_count=_edge_count;result._edge_positions.assign(_edge_count,{});for(intv=0;v<_n;v++){for(constauto&e:_g[v]){intidx=int(result._g[e.to].size());result._g[e.to].push_back(edge_type(e.to,e.from,e.cost,e.id,e.alive));if(0<=e.id&&e.id<_edge_count)result._edge_positions[e.id].push_back({e.to,idx});}}returnresult;}};}// namespace graph}// namespace m1une#line 9 "graph/cycle_detection.hpp"
namespacem1une{namespacegraph{structCycle{std::vector<int>vertices;std::vector<int>edge_ids;boolempty()const{returnvertices.empty();}};inlineCyclerestore_cycle(intfrom,intto,intclosing_edge,conststd::vector<int>&parent,conststd::vector<int>&parent_edge){Cycleresult;result.vertices.push_back(to);std::vector<int>middle_vertices;std::vector<int>middle_edges;for(intv=from;v!=to;v=parent[v]){middle_vertices.push_back(v);middle_edges.push_back(parent_edge[v]);}std::reverse(middle_vertices.begin(),middle_vertices.end());std::reverse(middle_edges.begin(),middle_edges.end());result.vertices.insert(result.vertices.end(),middle_vertices.begin(),middle_vertices.end());result.vertices.push_back(to);result.edge_ids.insert(result.edge_ids.end(),middle_edges.begin(),middle_edges.end());result.edge_ids.push_back(closing_edge);returnresult;}template<classT>Cyclefind_directed_cycle(constGraph<T>&g){intn=g.size();std::vector<int>color(n,0),parent(n,-1),parent_edge(n,-1);structFrame{intvertex;std::size_tnext_edge;};std::vector<Frame>stack;stack.reserve(n);for(intstart=0;start<n;start++){if(color[start]!=0)continue;color[start]=1;stack.push_back(Frame{start,0});while(!stack.empty()){Frame&frame=stack.back();constintvertex=frame.vertex;constauto&adjacency=g[vertex];while(frame.next_edge<adjacency.size()&&!adjacency[frame.next_edge].alive){frame.next_edge++;}if(frame.next_edge==adjacency.size()){color[vertex]=2;stack.pop_back();continue;}constauto&edge=adjacency[frame.next_edge++];constintto=edge.to;constintedge_id=edge.id;if(color[to]==0){parent[to]=vertex;parent_edge[to]=edge_id;color[to]=1;stack.push_back(Frame{to,0});}elseif(color[to]==1){returnrestore_cycle(vertex,to,edge_id,parent,parent_edge);}}}returnCycle();}template<classT>Cyclefind_undirected_cycle(constGraph<T>&g){intn=g.size();std::vector<int>color(n,0),parent(n,-1),parent_edge(n,-1);structFrame{intvertex;std::size_tnext_edge;};std::vector<Frame>stack;stack.reserve(n);for(intstart=0;start<n;start++){if(color[start]!=0)continue;color[start]=1;stack.push_back(Frame{start,0});while(!stack.empty()){Frame&frame=stack.back();constintvertex=frame.vertex;constauto&adjacency=g[vertex];while(frame.next_edge<adjacency.size()&&(!adjacency[frame.next_edge].alive||adjacency[frame.next_edge].id==parent_edge[vertex])){frame.next_edge++;}if(frame.next_edge==adjacency.size()){color[vertex]=2;stack.pop_back();continue;}constauto&edge=adjacency[frame.next_edge++];constintto=edge.to;constintedge_id=edge.id;if(color[to]==0){parent[to]=vertex;parent_edge[to]=edge_id;color[to]=1;stack.push_back(Frame{to,0});}elseif(color[to]==1){returnrestore_cycle(vertex,to,edge_id,parent,parent_edge);}}}returnCycle();}}// namespace graph}// namespace m1une#line 1 "graph/dag.hpp"
#line 1 "graph/dag_longest_path.hpp"
#line 6 "graph/dag_longest_path.hpp"
#include<limits>
#line 9 "graph/dag_longest_path.hpp"
#line 1 "graph/topological_sort.hpp"
#line 5 "graph/topological_sort.hpp"
#include<queue>
#line 7 "graph/topological_sort.hpp"
#line 9 "graph/topological_sort.hpp"
namespacem1une{namespacegraph{template<classT>std::optional<std::vector<int>>topological_sort(constGraph<T>&g){intn=g.size();std::vector<int>indeg(n,0);for(intv=0;v<n;v++){for(constauto&e:g[v]){if(!e.alive)continue;indeg[e.to]++;}}std::queue<int>que;for(intv=0;v<n;v++){if(indeg[v]==0)que.push(v);}std::vector<int>order;order.reserve(n);while(!que.empty()){intv=que.front();que.pop();order.push_back(v);for(constauto&e:g[v]){if(!e.alive)continue;indeg[e.to]--;if(indeg[e.to]==0)que.push(e.to);}}if(int(order.size())!=n)returnstd::nullopt;returnorder;}template<classT>boolis_dag(constGraph<T>&g){returntopological_sort(g).has_value();}}// namespace graph}// namespace m1une#line 12 "graph/dag_longest_path.hpp"
namespacem1une{namespacegraph{template<classT>structDagLongestPathResult{std::vector<T>dist;std::vector<int>parent;std::vector<int>parent_edge;std::vector<int>topological_order;Tneg_inf;boolreachable(intv)const{assert(0<=v&&v<int(dist.size()));returndist[v]!=neg_inf;}std::vector<int>path(intt)const{assert(reachable(t));std::vector<int>result;for(intv=t;v!=-1;v=parent[v])result.push_back(v);std::reverse(result.begin(),result.end());returnresult;}};template<classT>std::optional<DagLongestPathResult<T>>dag_longest_path(constGraph<T>&g,conststd::vector<int>&sources,Tneg_inf=std::numeric_limits<T>::lowest()/T(4)){constintn=g.size();autoorder=topological_sort(g);if(!order)returnstd::nullopt;DagLongestPathResult<T>result;result.dist.assign(n,neg_inf);result.parent.assign(n,-1);result.parent_edge.assign(n,-1);result.topological_order=*order;result.neg_inf=neg_inf;for(ints:sources){assert(0<=s&&s<n);result.dist[s]=T(0);}for(intv:*order){if(result.dist[v]==neg_inf)continue;for(constauto&e:g[v]){if(!e.alive)continue;Tnd=result.dist[v]+e.cost;if(result.dist[e.to]>=nd)continue;result.dist[e.to]=nd;result.parent[e.to]=v;result.parent_edge[e.to]=e.id;}}returnresult;}template<classT>std::optional<DagLongestPathResult<T>>dag_longest_path(constGraph<T>&g,ints,Tneg_inf=std::numeric_limits<T>::lowest()/T(4)){returndag_longest_path(g,std::vector<int>{s},neg_inf);}}// namespace graph}// namespace m1une#line 1 "graph/dag_path_count.hpp"
#line 7 "graph/dag_path_count.hpp"
#line 10 "graph/dag_path_count.hpp"
namespacem1une{namespacegraph{template<classCount=longlong,classT>std::optional<std::vector<Count>>dag_path_count(constGraph<T>&g,conststd::vector<int>&sources){constintn=g.size();autoorder=topological_sort(g);if(!order)returnstd::nullopt;std::vector<Count>ways(n,Count(0));std::vector<char>used_source(n,false);for(ints:sources){assert(0<=s&&s<n);if(used_source[s])continue;used_source[s]=true;ways[s]+=Count(1);}for(intv:*order){for(constauto&e:g[v]){if(e.alive)ways[e.to]+=ways[v];}}returnways;}template<classCount=longlong,classT>std::optional<std::vector<Count>>dag_path_count(constGraph<T>&g,ints){returndag_path_count<Count>(g,std::vector<int>{s});}}// namespace graph}// namespace m1une#line 1 "graph/dag_path_cover.hpp"
#line 7 "graph/dag_path_cover.hpp"
#line 1 "graph/bipartite.hpp"
#line 13 "graph/bipartite.hpp"
#line 15 "graph/bipartite.hpp"
namespacem1une{namespacegraph{structBipartiteResult{boolis_bipartite;std::vector<int>color;std::vector<int>left_vertices;std::vector<int>right_vertices;std::vector<int>left_id;std::vector<int>right_id;};template<classT>BipartiteResultbipartite(constGraph<T>&g){intn=g.size();BipartiteResultresult;result.is_bipartite=true;result.color.assign(n,-1);result.left_id.assign(n,-1);result.right_id.assign(n,-1);std::vector<std::vector<int>>adjacency(n);for(constauto&e:g.edges()){adjacency[e.from].push_back(e.to);adjacency[e.to].push_back(e.from);}std::queue<int>que;for(ints=0;s<n;s++){if(result.color[s]!=-1)continue;result.color[s]=0;que.push(s);while(!que.empty()){intv=que.front();que.pop();for(intto:adjacency[v]){if(result.color[to]==-1){result.color[to]=result.color[v]^1;que.push(to);}elseif(result.color[to]==result.color[v]){result.is_bipartite=false;returnresult;}}}}for(intv=0;v<n;v++){if(result.color[v]==0){result.left_id[v]=int(result.left_vertices.size());result.left_vertices.push_back(v);}else{result.right_id[v]=int(result.right_vertices.size());result.right_vertices.push_back(v);}}returnresult;}template<classT>boolis_bipartite(constGraph<T>&g){returnbipartite(g).is_bipartite;}structBipartiteVertexSet{std::vector<int>left;std::vector<int>right;intsize()const{returnint(left.size()+right.size());}};structBipartiteMatching{structEdge{intleft;intright;intid;boolalive;};structPair{intleft;intright;intedge_id;};private:int_left_size;int_right_size;std::vector<Edge>_edges;std::vector<std::vector<int>>_adj;std::vector<std::vector<int>>_radj;std::vector<int>_left_match;std::vector<int>_right_match;std::vector<int>_left_match_edge;std::vector<int>_right_match_edge;bool_calculated;voidinvalidate(){_calculated=false;}voidensure_matching(){if(!_calculated)max_matching();}public:BipartiteMatching():BipartiteMatching(0,0){}BipartiteMatching(intleft_size,intright_size):_left_size(left_size),_right_size(right_size),_adj(left_size),_radj(right_size),_left_match(left_size,-1),_right_match(right_size,-1),_left_match_edge(left_size,-1),_right_match_edge(right_size,-1),_calculated(false){assert(0<=left_size);assert(0<=right_size);}intleft_size()const{return_left_size;}intright_size()const{return_right_size;}intedge_count()const{returnint(_edges.size());}intadd_edge(intleft,intright){assert(0<=left&&left<_left_size);assert(0<=right&&right<_right_size);intid=int(_edges.size());_edges.push_back(Edge{left,right,id,true});_adj[left].push_back(id);_radj[right].push_back(id);invalidate();returnid;}Edgeget_edge(inti)const{assert(0<=i&&i<int(_edges.size()));return_edges[i];}std::vector<Edge>edges(boolinclude_inactive=false)const{std::vector<Edge>result;result.reserve(_edges.size());for(constauto&e:_edges){if(include_inactive||e.alive)result.push_back(e);}returnresult;}voidset_edge_alive(intid,boolalive){assert(0<=id&&id<int(_edges.size()));_edges[id].alive=alive;invalidate();}voiderase_edge(intid){set_edge_alive(id,false);}voidrevive_edge(intid){set_edge_alive(id,true);}boolis_edge_alive(intid)const{assert(0<=id&&id<int(_edges.size()));return_edges[id].alive;}intmax_matching(){_left_match.assign(_left_size,-1);_right_match.assign(_right_size,-1);_left_match_edge.assign(_left_size,-1);_right_match_edge.assign(_right_size,-1);std::vector<int>dist(_left_size);autobfs=[&]()->bool{std::queue<int>que;boolfound=false;for(intl=0;l<_left_size;l++){if(_left_match[l]==-1){dist[l]=0;que.push(l);}else{dist[l]=-1;}}while(!que.empty()){intl=que.front();que.pop();for(intid:_adj[l]){constauto&e=_edges[id];if(!e.alive)continue;intnext_left=_right_match[e.right];if(next_left==-1){found=true;}elseif(dist[next_left]==-1){dist[next_left]=dist[l]+1;que.push(next_left);}}}returnfound;};autodfs=[&](autoself,intl)->bool{for(intid:_adj[l]){constauto&e=_edges[id];if(!e.alive)continue;intnext_left=_right_match[e.right];if(next_left!=-1&&(dist[next_left]!=dist[l]+1||!self(self,next_left))){continue;}_left_match[l]=e.right;_right_match[e.right]=l;_left_match_edge[l]=id;_right_match_edge[e.right]=id;returntrue;}dist[l]=-1;returnfalse;};intresult=0;while(bfs()){for(intl=0;l<_left_size;l++){if(_left_match[l]==-1&&dfs(dfs,l))result++;}}_calculated=true;returnresult;}intmatching_size(){ensure_matching();intresult=0;for(intright:_left_match){if(right!=-1)result++;}returnresult;}std::vector<int>left_match(){ensure_matching();return_left_match;}std::vector<int>right_match(){ensure_matching();return_right_match;}std::vector<Pair>matching(){ensure_matching();std::vector<Pair>result;for(intl=0;l<_left_size;l++){if(_left_match[l]!=-1)result.push_back(Pair{l,_left_match[l],_left_match_edge[l]});}returnresult;}BipartiteVertexSetminimum_vertex_cover(){ensure_matching();std::vector<char>visited_left(_left_size,false),visited_right(_right_size,false);std::queue<int>que;for(intl=0;l<_left_size;l++){if(_left_match[l]==-1){visited_left[l]=true;que.push(l);}}while(!que.empty()){intl=que.front();que.pop();for(intid:_adj[l]){constauto&e=_edges[id];if(!e.alive||_left_match_edge[l]==id||visited_right[e.right])continue;visited_right[e.right]=true;intnext_left=_right_match[e.right];if(next_left!=-1&&!visited_left[next_left]){visited_left[next_left]=true;que.push(next_left);}}}BipartiteVertexSetresult;for(intl=0;l<_left_size;l++){if(!visited_left[l])result.left.push_back(l);}for(intr=0;r<_right_size;r++){if(visited_right[r])result.right.push_back(r);}returnresult;}BipartiteVertexSetmaximum_independent_set(){autocover=minimum_vertex_cover();std::vector<char>in_left_cover(_left_size,false),in_right_cover(_right_size,false);for(intl:cover.left)in_left_cover[l]=true;for(intr:cover.right)in_right_cover[r]=true;BipartiteVertexSetresult;for(intl=0;l<_left_size;l++){if(!in_left_cover[l])result.left.push_back(l);}for(intr=0;r<_right_size;r++){if(!in_right_cover[r])result.right.push_back(r);}returnresult;}std::optional<std::vector<int>>minimum_edge_cover(){ensure_matching();std::vector<int>result;std::vector<char>covered_left(_left_size,false),covered_right(_right_size,false);std::vector<char>used_edge(_edges.size(),false);autouse_edge=[&](intid){if(used_edge[id])return;used_edge[id]=true;result.push_back(id);covered_left[_edges[id].left]=true;covered_right[_edges[id].right]=true;};for(intl=0;l<_left_size;l++){if(_left_match_edge[l]!=-1)use_edge(_left_match_edge[l]);}for(intl=0;l<_left_size;l++){if(covered_left[l])continue;intid=-1;for(intedge_id:_adj[l]){if(_edges[edge_id].alive){id=edge_id;break;}}if(id==-1)returnstd::nullopt;use_edge(id);}for(intr=0;r<_right_size;r++){if(covered_right[r])continue;intid=-1;for(intedge_id:_radj[r]){if(_edges[edge_id].alive){id=edge_id;break;}}if(id==-1)returnstd::nullopt;use_edge(id);}returnresult;}};structBipartiteMatchingGraph{BipartiteResultparts;BipartiteMatchingmatching;std::vector<int>original_edge_id;intleft_vertex(intleft)const{assert(0<=left&&left<int(parts.left_vertices.size()));returnparts.left_vertices[left];}intright_vertex(intright)const{assert(0<=right&&right<int(parts.right_vertices.size()));returnparts.right_vertices[right];}intoriginal_edge(intedge_id)const{assert(0<=edge_id&&edge_id<int(original_edge_id.size()));returnoriginal_edge_id[edge_id];}};template<classT>std::optional<BipartiteMatchingGraph>make_bipartite_matching(constGraph<T>&g){autoparts=bipartite(g);if(!parts.is_bipartite)returnstd::nullopt;BipartiteMatchingGraphresult;result.parts=parts;result.matching=BipartiteMatching(int(parts.left_vertices.size()),int(parts.right_vertices.size()));for(constauto&e:g.edges()){intleft,right;if(parts.color[e.from]==0){left=parts.left_id[e.from];right=parts.right_id[e.to];}else{left=parts.left_id[e.to];right=parts.right_id[e.from];}intid=result.matching.add_edge(left,right);if(int(result.original_edge_id.size())<=id)result.original_edge_id.resize(id+1);result.original_edge_id[id]=e.id;}returnresult;}structBipartiteEdgeColoringResult{intcolor_count;std::vector<int>color;};namespacedetail{structBipartiteEdgeColoringGroups{intcount;std::vector<int>group;};inlineBipartiteEdgeColoringGroupsgroup_vertices(conststd::vector<int>°ree,intmaximum_degree){BipartiteEdgeColoringGroupsresult;result.count=0;result.group.assign(degree.size(),-1);intcurrent_degree=0;for(intvertex=0;vertex<int(degree.size());vertex++){if(degree[vertex]==0)continue;if(result.count==0||current_degree+degree[vertex]>maximum_degree){result.count++;current_degree=0;}result.group[vertex]=result.count-1;current_degree+=degree[vertex];}returnresult;}classBipartiteEdgeColoringSolver{private:int_side_size;int_original_edge_count;std::vector<int>_left;std::vector<int>_right;std::vector<int>_color;std::vector<int>_used_stamp;int_stamp;intother_endpoint(intvertex,intedge)const{if(vertex<_side_size)return_side_size+_right[edge];return_left[edge];}std::vector<int>perfect_matching(conststd::vector<int>&edge_ids)const{std::vector<std::vector<int>>adjacency(_side_size);for(intedge:edge_ids)adjacency[_left[edge]].push_back(edge);std::vector<int>right_match(_side_size,-1);std::vector<int>left_match_edge(_side_size,-1);intmatching_size=0;for(intleft=0;left<_side_size;left++){for(intedge:adjacency[left]){intright=_right[edge];if(right_match[right]!=-1)continue;right_match[right]=left;left_match_edge[left]=edge;matching_size++;break;}}std::vector<int>distance(_side_size);std::vector<int>next_edge(_side_size);std::vector<int>left_stack;std::vector<int>path_edges;left_stack.reserve(_side_size);path_edges.reserve(_side_size);while(matching_size<_side_size){std::queue<int>queue;std::fill(distance.begin(),distance.end(),-1);for(intleft=0;left<_side_size;left++){if(left_match_edge[left]!=-1)continue;distance[left]=0;queue.push(left);}boolreachable_free_right=false;while(!queue.empty()){intleft=queue.front();queue.pop();for(intedge:adjacency[left]){intnext_left=right_match[_right[edge]];if(next_left==-1){reachable_free_right=true;}elseif(distance[next_left]==-1){distance[next_left]=distance[left]+1;queue.push(next_left);}}}assert(reachable_free_right);std::fill(next_edge.begin(),next_edge.end(),0);intaugmented=0;for(introot=0;root<_side_size;root++){if(left_match_edge[root]!=-1||distance[root]==-1)continue;left_stack.clear();path_edges.clear();left_stack.push_back(root);boolfound=false;while(!left_stack.empty()&&!found){intleft=left_stack.back();booladvanced=false;while(next_edge[left]<int(adjacency[left].size())){intedge=adjacency[left][next_edge[left]++];intright=_right[edge];intnext_left=right_match[right];if(next_left==-1){left_match_edge[left]=edge;right_match[right]=left;for(intindex=int(path_edges.size())-1;index>=0;index--){intpath_edge=path_edges[index];intpath_left=left_stack[index];left_match_edge[path_left]=path_edge;right_match[_right[path_edge]]=path_left;}found=true;break;}if(distance[next_left]!=distance[left]+1)continue;path_edges.push_back(edge);left_stack.push_back(next_left);advanced=true;break;}if(found||advanced)continue;distance[left]=-1;left_stack.pop_back();if(path_edges.size()==left_stack.size()&&!path_edges.empty()){path_edges.pop_back();}}if(found)augmented++;}assert(augmented>0);matching_size+=augmented;}returnleft_match_edge;}std::pair<std::vector<int>,std::vector<int>>split_even(conststd::vector<int>&edge_ids){std::vector<std::vector<int>>incidence(std::size_t(2)*_side_size);for(intedge:edge_ids){incidence[_left[edge]].push_back(edge);incidence[_side_size+_right[edge]].push_back(edge);}_stamp++;assert(_stamp>0);std::vector<int>next_edge(std::size_t(2)*_side_size,0);std::vector<int>first;std::vector<int>second;first.reserve(edge_ids.size()/2);second.reserve(edge_ids.size()/2);for(intstart=0;start<2*_side_size;start++){while(true){while(next_edge[start]<int(incidence[start].size())&&_used_stamp[incidence[start][next_edge[start]]]==_stamp){next_edge[start]++;}if(next_edge[start]==int(incidence[start].size()))break;intvertex=start;boolparity=false;do{while(next_edge[vertex]<int(incidence[vertex].size())&&_used_stamp[incidence[vertex][next_edge[vertex]]]==_stamp){next_edge[vertex]++;}assert(next_edge[vertex]<int(incidence[vertex].size()));intedge=incidence[vertex][next_edge[vertex]++];_used_stamp[edge]=_stamp;if(!parity){first.push_back(edge);}else{second.push_back(edge);}parity=!parity;vertex=other_endpoint(vertex,edge);}while(vertex!=start);assert(!parity);}}assert(first.size()==second.size());return{std::move(first),std::move(second)};}voidcolor_regular(conststd::vector<int>&edge_ids,intdegree,intoffset){assert(std::size_t(_side_size)*std::size_t(degree)==edge_ids.size());if(degree==0)return;if(degree==1){for(intedge:edge_ids){if(edge<_original_edge_count)_color[edge]=offset;}return;}if(degree%2==1){std::vector<int>matching=perfect_matching(edge_ids);_stamp++;assert(_stamp>0);for(intedge:matching){_used_stamp[edge]=_stamp;if(edge<_original_edge_count)_color[edge]=offset;}std::vector<int>remaining;remaining.reserve(edge_ids.size()-matching.size());for(intedge:edge_ids){if(_used_stamp[edge]!=_stamp)remaining.push_back(edge);}color_regular(remaining,degree-1,offset+1);return;}auto[first,second]=split_even(edge_ids);color_regular(first,degree/2,offset);color_regular(second,degree/2,offset+degree/2);}public:BipartiteEdgeColoringSolver(intside_size,intoriginal_edge_count,std::vector<int>left,std::vector<int>right):_side_size(side_size),_original_edge_count(original_edge_count),_left(std::move(left)),_right(std::move(right)),_color(original_edge_count,-1),_used_stamp(_left.size(),0),_stamp(0){}std::vector<int>solve(intdegree){std::vector<int>edge_ids(_left.size());for(intedge=0;edge<int(edge_ids.size());edge++)edge_ids[edge]=edge;color_regular(edge_ids,degree,0);for(intcolor:_color)assert(0<=color&&color<degree);return_color;}};}// namespace detail// Returns an optimal edge coloring of a bipartite multigraph.inlineBipartiteEdgeColoringResultbipartite_edge_coloring(intleft_size,intright_size,conststd::vector<std::pair<int,int>>&edges){assert(left_size>=0);assert(right_size>=0);assert(edges.size()<=std::size_t(std::numeric_limits<int>::max()));std::vector<int>left_degree(left_size,0);std::vector<int>right_degree(right_size,0);intmaximum_degree=0;for(auto[left,right]:edges){assert(0<=left&&left<left_size);assert(0<=right&&right<right_size);left_degree[left]++;right_degree[right]++;maximum_degree=std::max(maximum_degree,left_degree[left]);maximum_degree=std::max(maximum_degree,right_degree[right]);}BipartiteEdgeColoringResultresult;result.color_count=maximum_degree;if(edges.empty())returnresult;detail::BipartiteEdgeColoringGroupsleft_groups=detail::group_vertices(left_degree,maximum_degree);detail::BipartiteEdgeColoringGroupsright_groups=detail::group_vertices(right_degree,maximum_degree);intside_size=std::max(left_groups.count,right_groups.count);std::vector<int>contracted_left;std::vector<int>contracted_right;contracted_left.reserve(std::size_t(3)*edges.size());contracted_right.reserve(std::size_t(3)*edges.size());std::vector<int>contracted_left_degree(side_size,0);std::vector<int>contracted_right_degree(side_size,0);for(auto[left,right]:edges){intcontracted_left_vertex=left_groups.group[left];intcontracted_right_vertex=right_groups.group[right];contracted_left.push_back(contracted_left_vertex);contracted_right.push_back(contracted_right_vertex);contracted_left_degree[contracted_left_vertex]++;contracted_right_degree[contracted_right_vertex]++;}intleft=0;intright=0;while(true){while(left<side_size&&contracted_left_degree[left]==maximum_degree)left++;while(right<side_size&&contracted_right_degree[right]==maximum_degree)right++;if(left==side_size||right==side_size)break;contracted_left.push_back(left);contracted_right.push_back(right);contracted_left_degree[left]++;contracted_right_degree[right]++;}assert(left==side_size&&right==side_size);assert(contracted_left.size()==std::size_t(side_size)*std::size_t(maximum_degree));detail::BipartiteEdgeColoringSolversolver(side_size,int(edges.size()),std::move(contracted_left),std::move(contracted_right));result.color=solver.solve(maximum_degree);returnresult;}}// namespace graph}// namespace m1une#line 11 "graph/dag_path_cover.hpp"
namespacem1une{namespacegraph{structDagPathCoverResult{std::vector<std::vector<int>>paths;std::vector<std::vector<int>>path_edge_ids;std::vector<int>predecessor;std::vector<int>successor;std::vector<int>predecessor_edge;std::vector<int>successor_edge;intsize()const{returnint(paths.size());}};template<classT>std::optional<DagPathCoverResult>minimum_dag_path_cover(constGraph<T>&g){constintn=g.size();if(!topological_sort(g))returnstd::nullopt;BipartiteMatchingmatching(n,n);std::vector<int>original_edge_id;for(intv=0;v<n;v++){for(constauto&e:g[v]){if(!e.alive)continue;matching.add_edge(v,e.to);original_edge_id.push_back(e.id);}}DagPathCoverResultresult;result.predecessor.assign(n,-1);result.successor.assign(n,-1);result.predecessor_edge.assign(n,-1);result.successor_edge.assign(n,-1);for(constauto&pair:matching.matching()){constintedge_id=original_edge_id[pair.edge_id];result.successor[pair.left]=pair.right;result.successor_edge[pair.left]=edge_id;result.predecessor[pair.right]=pair.left;result.predecessor_edge[pair.right]=edge_id;}intcovered=0;for(ints=0;s<n;s++){if(result.predecessor[s]!=-1)continue;result.paths.emplace_back();result.path_edge_ids.emplace_back();for(intv=s;v!=-1;v=result.successor[v]){result.paths.back().push_back(v);covered++;if(result.successor_edge[v]!=-1){result.path_edge_ids.back().push_back(result.successor_edge[v]);}}}assert(covered==n);returnresult;}}// namespace graph}// namespace m1une#line 1 "graph/dag_reachability.hpp"
#line 9 "graph/dag_reachability.hpp"
#line 1 "utilities/dynamic_bitset.hpp"
#line 9 "utilities/dynamic_bitset.hpp"
namespacem1une{namespaceutilities{structDynamicBitset{private:staticconstexprintBITS_PER_BLOCK=64;staticconstexpruint64_tFULL_BLOCK=~uint64_t{0};int_n;std::vector<uint64_t>blocks;staticintblock_count(intn){assert(n>=0);return(n+BITS_PER_BLOCK-1)>>6;}uint64_ttail_mask()const{constintrem=_n&(BITS_PER_BLOCK-1);returnrem==0?FULL_BLOCK:((uint64_t{1}<<rem)-1);}// Keep unused bits in the last block equal to zero.voidclean(){if(!blocks.empty())blocks.back()&=tail_mask();}public:DynamicBitset():_n(0),blocks(){}explicitDynamicBitset(intn,boolval=false):_n(n),blocks(block_count(n),val?FULL_BLOCK:0){if(val)clean();}// Returns the logical number of bits.intsize()const{return_n;}// Returns whether the bit at index i is set.booltest(inti)const{assert(0<=i&&i<_n);return(blocks[i>>6]>>(i&(BITS_PER_BLOCK-1)))&1;}// Sets the bit at index i to true.voidset(inti){assert(0<=i&&i<_n);blocks[i>>6]|=uint64_t{1}<<(i&(BITS_PER_BLOCK-1));}// Sets all bits to true.voidset(){std::fill(blocks.begin(),blocks.end(),FULL_BLOCK);clean();}// Sets the bit at index i to false.voidreset(inti){assert(0<=i&&i<_n);blocks[i>>6]&=~(uint64_t{1}<<(i&(BITS_PER_BLOCK-1)));}// Sets all bits to false.voidreset(){std::fill(blocks.begin(),blocks.end(),uint64_t{0});}// Flips the bit at index i.voidflip(inti){assert(0<=i&&i<_n);blocks[i>>6]^=uint64_t{1}<<(i&(BITS_PER_BLOCK-1));}// Flips all bits.voidflip(){for(uint64_t&block:blocks)block=~block;clean();}// Returns the number of set bits.intpopcount()const{intres=0;for(uint64_tblock:blocks)res+=__builtin_popcountll(block);returnres;}// Returns the index of the least significant set bit, or -1 if no bit is set.intlowbit()const{constintm=static_cast<int>(blocks.size());for(inti=0;i<m;++i){if(blocks[i]!=0)return(i<<6)+__builtin_ctzll(blocks[i]);}return-1;}// Returns the index of the most significant set bit, or -1 if no bit is set.inttopbit()const{for(inti=static_cast<int>(blocks.size())-1;i>=0;--i){if(blocks[i]!=0)return(i<<6)+(BITS_PER_BLOCK-1-__builtin_clzll(blocks[i]));}return-1;}// Returns whether at least one bit is set.boolany()const{for(uint64_tblock:blocks){if(block!=0)returntrue;}returnfalse;}// Returns whether every logical bit is set.boolall()const{if(_n==0)returntrue;constintm=static_cast<int>(blocks.size());for(inti=0;i+1<m;++i){if(blocks[i]!=FULL_BLOCK)returnfalse;}returnblocks.back()==tail_mask();}// Returns whether no bit is set.boolnone()const{return!any();}DynamicBitset&operator&=(constDynamicBitset&other){assert(_n==other._n);conststd::size_tm=blocks.size();for(std::size_ti=0;i<m;++i)blocks[i]&=other.blocks[i];return*this;}DynamicBitset&operator|=(constDynamicBitset&other){assert(_n==other._n);conststd::size_tm=blocks.size();for(std::size_ti=0;i<m;++i)blocks[i]|=other.blocks[i];return*this;}DynamicBitset&operator^=(constDynamicBitset&other){assert(_n==other._n);conststd::size_tm=blocks.size();for(std::size_ti=0;i<m;++i)blocks[i]^=other.blocks[i];return*this;}DynamicBitsetoperator~()const{DynamicBitsetres=*this;res.flip();returnres;}friendDynamicBitsetoperator&(DynamicBitsetlhs,constDynamicBitset&rhs){lhs&=rhs;returnlhs;}friendDynamicBitsetoperator|(DynamicBitsetlhs,constDynamicBitset&rhs){lhs|=rhs;returnlhs;}friendDynamicBitsetoperator^(DynamicBitsetlhs,constDynamicBitset&rhs){lhs^=rhs;returnlhs;}};}// namespace utilities}// namespace m1une#line 13 "graph/dag_reachability.hpp"
namespacem1une{namespacegraph{structDagReachability{std::vector<utilities::DynamicBitset>reachable_vertices;std::vector<int>topological_order;intsize()const{returnint(reachable_vertices.size());}boolreachable(intfrom,intto)const{assert(0<=from&&from<size());assert(0<=to&&to<size());returnreachable_vertices[from].test(to);}};template<classT>std::optional<DagReachability>dag_reachability(constGraph<T>&g){constintn=g.size();autoorder=topological_sort(g);if(!order)returnstd::nullopt;DagReachabilityresult;result.reachable_vertices.assign(n,utilities::DynamicBitset(n));result.topological_order=*order;for(inti=n-1;i>=0;i--){intv=(*order)[i];result.reachable_vertices[v].set(v);for(constauto&e:g[v]){if(e.alive)result.reachable_vertices[v]|=result.reachable_vertices[e.to];}}returnresult;}template<classT>structDagTransitiveReductionResult{Graph<T>graph;std::vector<int>original_edge_ids;};template<classT>std::optional<DagTransitiveReductionResult<T>>dag_transitive_reduction(constGraph<T>&g){autoreachability=dag_reachability(g);if(!reachability)returnstd::nullopt;constintn=g.size();std::vector<int>position(n);for(inti=0;i<n;i++)position[reachability->topological_order[i]]=i;std::vector<char>kept(g.edge_count(),false);for(intv=0;v<n;v++){std::vector<constEdge<T>*>outgoing;outgoing.reserve(g[v].size());for(constauto&e:g[v]){if(e.alive)outgoing.push_back(&e);}std::stable_sort(outgoing.begin(),outgoing.end(),[&](constauto*lhs,constauto*rhs){returnposition[lhs->to]<position[rhs->to];});utilities::DynamicBitsetcovered(n);for(constauto*e:outgoing){if(covered.test(e->to))continue;kept[e->id]=true;covered|=reachability->reachable_vertices[e->to];}}DagTransitiveReductionResult<T>result;result.graph=Graph<T>(n);for(intv=0;v<n;v++){for(constauto&e:g[v]){if(!e.alive||!kept[e.id])continue;result.graph.add_directed_edge(e.from,e.to,e.cost);result.original_edge_ids.push_back(e.id);}}returnresult;}}// namespace graph}// namespace m1une#line 1 "graph/dag_shortest_path.hpp"
#line 9 "graph/dag_shortest_path.hpp"
#line 12 "graph/dag_shortest_path.hpp"
namespacem1une{namespacegraph{template<classT>structDagShortestPathResult{std::vector<T>dist;std::vector<int>parent;std::vector<int>parent_edge;std::vector<int>topological_order;Tinf;boolreachable(intv)const{assert(0<=v&&v<int(dist.size()));returndist[v]!=inf;}std::vector<int>path(intt)const{assert(reachable(t));std::vector<int>result;for(intv=t;v!=-1;v=parent[v])result.push_back(v);std::reverse(result.begin(),result.end());returnresult;}};template<classT>std::optional<DagShortestPathResult<T>>dag_shortest_path(constGraph<T>&g,conststd::vector<int>&sources,Tinf=std::numeric_limits<T>::max()/T(4)){intn=g.size();autoorder=topological_sort(g);if(!order)returnstd::nullopt;DagShortestPathResult<T>result;result.dist.assign(n,inf);result.parent.assign(n,-1);result.parent_edge.assign(n,-1);result.topological_order=*order;result.inf=inf;for(ints:sources){assert(0<=s&&s<n);if(result.dist[s]==T(0))continue;result.dist[s]=T(0);}for(intv:*order){if(result.dist[v]==inf)continue;for(constauto&e:g[v]){if(!e.alive)continue;Tnd=result.dist[v]+e.cost;if(result.dist[e.to]<=nd)continue;result.dist[e.to]=nd;result.parent[e.to]=v;result.parent_edge[e.to]=e.id;}}returnresult;}template<classT>std::optional<DagShortestPathResult<T>>dag_shortest_path(constGraph<T>&g,ints,Tinf=std::numeric_limits<T>::max()/T(4)){returndag_shortest_path(g,std::vector<int>{s},inf);}}// namespace graph}// namespace m1une#line 10 "graph/dag.hpp"
#line 1 "graph/dfs.hpp"
#line 6 "graph/dfs.hpp"
#include<concepts>
#include<functional>
#line 10 "graph/dfs.hpp"
#line 12 "graph/dfs.hpp"
namespacem1une{namespacegraph{structDfsResult{std::vector<int>depth;std::vector<int>parent;std::vector<int>parent_edge;std::vector<int>root;std::vector<int>tin;std::vector<int>tout;std::vector<int>preorder;std::vector<int>postorder;std::vector<int>roots;boolreachable(intvertex)const{assert(0<=vertex&&vertex<int(depth.size()));returndepth[vertex]!=-1;}intcomponent_count()const{returnint(roots.size());}std::vector<int>path(inttarget)const{assert(reachable(target));std::vector<int>result;for(intvertex=target;vertex!=-1;vertex=parent[vertex]){result.push_back(vertex);}std::reverse(result.begin(),result.end());returnresult;}boolis_ancestor(intancestor,intvertex)const{assert(0<=ancestor&&ancestor<int(depth.size()));assert(0<=vertex&&vertex<int(depth.size()));if(!reachable(ancestor)||!reachable(vertex))returnfalse;returntin[ancestor]<=tin[vertex]&&tout[vertex]<=tout[ancestor];}};namespacedfs_detail{template<classCallback>conceptDfsCallback=std::invocable<Callback&,int,int>||std::invocable<Callback&,int>;template<DfsCallbackCallback>voidinvoke_callback(Callback&callback,intvertex,intparent){ifconstexpr(std::invocable<Callback&,int,int>){std::invoke(callback,vertex,parent);}else{std::invoke(callback,vertex);}}template<classT,classCallback>DfsResultrun_dfs(constGraph<T>&graph,conststd::vector<int>&sources,boolcomplete_forest,Callback&callback){constintn=graph.size();DfsResultresult;result.depth.assign(n,-1);result.parent.assign(n,-1);result.parent_edge.assign(n,-1);result.root.assign(n,-1);result.tin.assign(n,-1);result.tout.assign(n,-1);result.preorder.reserve(n);result.postorder.reserve(n);result.roots.reserve(n);structFrame{intvertex;intnext_edge;};std::vector<Frame>stack;stack.reserve(n);inttimer=0;autotraverse=[&](intsource){assert(0<=source&&source<n);if(result.reachable(source))return;result.depth[source]=0;result.root[source]=source;result.tin[source]=++timer;result.preorder.push_back(source);result.roots.push_back(source);invoke_callback(callback,source,-1);stack.push_back(Frame{source,0});while(!stack.empty()){Frame&frame=stack.back();intvertex=frame.vertex;if(frame.next_edge==int(graph[vertex].size())){result.tout[vertex]=++timer;result.postorder.push_back(vertex);stack.pop_back();continue;}constEdge<T>&edge=graph[vertex][frame.next_edge++];if(!edge.alive||result.reachable(edge.to))continue;result.depth[edge.to]=result.depth[vertex]+1;result.parent[edge.to]=vertex;result.parent_edge[edge.to]=edge.id;result.root[edge.to]=result.root[vertex];result.tin[edge.to]=++timer;result.preorder.push_back(edge.to);invoke_callback(callback,edge.to,vertex);stack.push_back(Frame{edge.to,0});}};for(intsource:sources)traverse(source);if(complete_forest){for(intvertex=0;vertex<n;vertex++)traverse(vertex);}returnresult;}}// namespace dfs_detailtemplate<classT>DfsResultdfs(constGraph<T>&graph,conststd::vector<int>&sources){autocallback=[](int){};returndfs_detail::run_dfs(graph,sources,false,callback);}template<classT>DfsResultdfs(constGraph<T>&graph,intsource){returndfs(graph,std::vector<int>{source});}template<classT>DfsResultdfs(constGraph<T>&graph){autocallback=[](int){};returndfs_detail::run_dfs(graph,std::vector<int>(),true,callback);}template<classT,classCallback>requiresdfs_detail::DfsCallback<Callback>DfsResultdfs(constGraph<T>&graph,conststd::vector<int>&sources,Callback&&callback){returndfs_detail::run_dfs(graph,sources,false,callback);}template<classT,classCallback>requiresdfs_detail::DfsCallback<Callback>DfsResultdfs(constGraph<T>&graph,intsource,Callback&&callback){returndfs(graph,std::vector<int>{source},std::forward<Callback>(callback));}template<classT,classCallback>requiresdfs_detail::DfsCallback<Callback>DfsResultdfs(constGraph<T>&graph,Callback&&callback){returndfs_detail::run_dfs(graph,std::vector<int>(),true,callback);}}// namespace graph}// namespace m1une#line 1 "graph/directed_mst.hpp"
#line 8 "graph/directed_mst.hpp"
#line 10 "graph/directed_mst.hpp"
namespacem1une{namespacegraph{template<classT>structDirectedMinimumSpanningTree{Tcost;std::vector<int>parent;std::vector<int>parent_edge;std::vector<Edge<T>>edges;introot;};namespaceinternal{template<classT>structDirectedMstEdge{intfrom=-1;intto=-1;Tcost=T(0);intid=-1;};template<classT>structDirectedMstHeapPool{usingStoredEdge=DirectedMstEdge<T>;structNode{StoredEdgeedge;Toffset=T(0);intchild=-1;intsibling=-1;};structHeap{introot=-1;intsize=0;};std::vector<Node>nodes;explicitDirectedMstHeapPool(intcapacity=0){nodes.reserve(capacity);}Tkey(intnode)const{returnnodes[node].edge.cost+nodes[node].offset;}intmeld_roots(intfirst,intsecond){if(first==-1)returnsecond;if(second==-1)returnfirst;if(key(second)<key(first))std::swap(first,second);nodes[second].offset-=nodes[first].offset;nodes[second].sibling=nodes[first].child;nodes[first].child=second;returnfirst;}voidpush(Heap&heap,constStoredEdge&edge){constintnode=int(nodes.size());nodes.push_back(Node{edge,T(0),-1,-1});heap.root=meld_roots(heap.root,node);heap.size++;}voidmeld(Heap&destination,Heap&source){destination.root=meld_roots(destination.root,source.root);destination.size+=source.size;source.root=-1;source.size=0;}constStoredEdge&top(constHeap&heap)const{assert(heap.root!=-1);returnnodes[heap.root].edge;}Ttop_key(constHeap&heap)const{assert(heap.root!=-1);returnkey(heap.root);}voidadd_all(Heap&heap,constT&delta){assert(heap.root!=-1);nodes[heap.root].offset+=delta;}voidpop(Heap&heap){assert(heap.root!=-1&&heap.size>0);constintold_root=heap.root;intchild=nodes[old_root].child;std::vector<int>pairs;while(child!=-1){intfirst=child;child=nodes[first].sibling;nodes[first].sibling=-1;nodes[first].offset+=nodes[old_root].offset;if(child!=-1){intsecond=child;child=nodes[second].sibling;nodes[second].sibling=-1;nodes[second].offset+=nodes[old_root].offset;first=meld_roots(first,second);}pairs.push_back(first);}heap.root=-1;for(autoit=pairs.rbegin();it!=pairs.rend();++it){heap.root=meld_roots(*it,heap.root);}heap.size--;}};structDirectedMstDsu{std::vector<int>parent;explicitDirectedMstDsu(intn):parent(n,-1){}intleader(intvertex){introot=vertex;while(parent[root]!=-1)root=parent[root];while(vertex!=root){intnext=parent[vertex];parent[vertex]=root;vertex=next;}returnroot;}};template<classT>structDirectedMstRootlessCost{intartificial_edges;Toriginal_cost;DirectedMstRootlessCost():artificial_edges(0),original_cost(T(0)){}explicitDirectedMstRootlessCost(intzero):artificial_edges(zero),original_cost(T(0)){assert(zero==0);}DirectedMstRootlessCost(intartificial_edges_,constT&original_cost_):artificial_edges(artificial_edges_),original_cost(original_cost_){}DirectedMstRootlessCost&operator+=(constDirectedMstRootlessCost&other){artificial_edges+=other.artificial_edges;original_cost+=other.original_cost;return*this;}DirectedMstRootlessCost&operator-=(constDirectedMstRootlessCost&other){artificial_edges-=other.artificial_edges;original_cost-=other.original_cost;return*this;}friendDirectedMstRootlessCostoperator+(DirectedMstRootlessCostfirst,constDirectedMstRootlessCost&second){returnfirst+=second;}friendDirectedMstRootlessCostoperator-(DirectedMstRootlessCostfirst,constDirectedMstRootlessCost&second){returnfirst-=second;}friendbooloperator<(constDirectedMstRootlessCost&first,constDirectedMstRootlessCost&second){if(first.artificial_edges!=second.artificial_edges){returnfirst.artificial_edges<second.artificial_edges;}returnfirst.original_cost<second.original_cost;}};}// namespace internal// Returns a minimum-cost spanning arborescence rooted at root, or nullopt when// some vertex is unreachable from the root using active directed edges.template<classT>std::optional<DirectedMinimumSpanningTree<T>>directed_mst(constGraph<T>&graph,introot){constintn=graph.size();assert(0<=root&&root<n);constintmaximum_node_count=2*n;intactive_edge_count=0;#ifndef NDEBUG
std::vector<int>incidence(graph.edge_count(),0);#endif
for(intvertex=0;vertex<n;vertex++){for(constEdge<T>&edge:graph[vertex]){if(!edge.alive)continue;assert(0<=edge.id&&edge.id<graph.edge_count());#ifndef NDEBUG
incidence[edge.id]++;#endif
active_edge_count++;}}#ifndef NDEBUG
for(intcount:incidence){if(count!=0)assert(count==1);}#endif
usingStoredEdge=internal::DirectedMstEdge<T>;usingHeapPool=internal::DirectedMstHeapPool<T>;HeapPoolpool(active_edge_count);std::vector<typenameHeapPool::Heap>heaps(maximum_node_count);for(intvertex=0;vertex<n;vertex++){for(constEdge<T>&edge:graph[vertex]){if(!edge.alive)continue;pool.push(heaps[edge.to],StoredEdge{edge.from,edge.to,edge.cost,edge.id});}}internal::DirectedMstDsudsu(maximum_node_count);std::vector<int>contraction_parent(maximum_node_count,-1);std::vector<int>visited(maximum_node_count,0);std::vector<StoredEdge>selected(maximum_node_count);intnode_count=n;intvisit_token=1;visited[root]=1;for(intstart=0;start<n;start++){if(visited[start]!=0)continue;visit_token++;intcomponent=start;while(visited[component]==0||visited[component]==visit_token){if(visited[component]==visit_token){if(node_count==maximum_node_count)returnstd::nullopt;constintcontracted=node_count++;intcurrent=component;do{constTreduction=T(0)-pool.top_key(heaps[current]);pool.add_all(heaps[current],reduction);pool.meld(heaps[contracted],heaps[current]);contraction_parent[current]=contracted;dsu.parent[current]=contracted;current=dsu.leader(selected[current].from);}while(current!=contracted);component=contracted;}assert(visited[component]==0);visited[component]=visit_token;while(heaps[component].size>0&&dsu.leader(pool.top(heaps[component]).from)==component){pool.pop(heaps[component]);}if(heaps[component].size==0)returnstd::nullopt;selected[component]=pool.top(heaps[component]);component=dsu.leader(selected[component].from);}}DirectedMinimumSpanningTree<T>result;result.cost=T(0);result.parent.assign(n,-1);result.parent_edge.assign(n,-1);result.root=root;result.parent[root]=root;std::vector<char>expanded(node_count,false);std::vector<StoredEdge>chosen(n);for(intcomponent=node_count-1;component>=0;component--){if(component==root||expanded[component])continue;constStoredEdge&edge=selected[component];if(edge.id==-1)returnstd::nullopt;intvertex=edge.to;while(vertex!=-1&&!expanded[vertex]){expanded[vertex]=true;vertex=contraction_parent[vertex];}result.cost+=edge.cost;result.parent[edge.to]=edge.from;result.parent_edge[edge.to]=edge.id;chosen[edge.to]=edge;}result.edges.reserve(n-1);for(intvertex=0;vertex<n;vertex++){if(vertex==root)continue;if(result.parent[vertex]==-1)returnstd::nullopt;constStoredEdge&edge=chosen[vertex];result.edges.emplace_back(edge.from,edge.to,edge.cost,edge.id,true);}returnresult;}// Chooses the root that gives a minimum-cost spanning arborescence.template<classT>std::optional<DirectedMinimumSpanningTree<T>>directed_mst(constGraph<T>&graph){constintn=graph.size();if(n==0)returnstd::nullopt;usingCost=internal::DirectedMstRootlessCost<T>;Graph<Cost>augmented(n+1);std::vector<int>original_edge_id;original_edge_id.reserve(graph.edge_count()+n);#ifndef NDEBUG
std::vector<int>incidence(graph.edge_count(),0);#endif
for(intvertex=0;vertex<n;vertex++){for(constEdge<T>&edge:graph[vertex]){if(!edge.alive)continue;#ifndef NDEBUG
assert(0<=edge.id&&edge.id<graph.edge_count());incidence[edge.id]++;#endif
augmented.add_directed_edge(edge.from,edge.to,Cost(0,edge.cost));original_edge_id.push_back(edge.id);}}#ifndef NDEBUG
for(intcount:incidence){if(count!=0)assert(count==1);}#endif
constintartificial_root=n;for(intvertex=0;vertex<n;vertex++){augmented.add_directed_edge(artificial_root,vertex,Cost(1,T(0)));original_edge_id.push_back(-1);}autoaugmented_result=directed_mst(augmented,artificial_root);if(!augmented_result||augmented_result->cost.artificial_edges!=1){returnstd::nullopt;}DirectedMinimumSpanningTree<T>result;result.cost=augmented_result->cost.original_cost;result.parent.assign(n,-1);result.parent_edge.assign(n,-1);result.root=-1;result.edges.reserve(n-1);for(intvertex=0;vertex<n;vertex++){intaugmented_edge_id=augmented_result->parent_edge[vertex];assert(0<=augmented_edge_id&&augmented_edge_id<int(original_edge_id.size()));intedge_id=original_edge_id[augmented_edge_id];if(edge_id==-1){assert(result.root==-1);result.root=vertex;result.parent[vertex]=vertex;continue;}result.parent[vertex]=augmented_result->parent[vertex];result.parent_edge[vertex]=edge_id;result.edges.emplace_back(result.parent[vertex],vertex,augmented_result->edges[vertex].cost.original_cost,edge_id,true);}assert(result.root!=-1);returnresult;}}// namespace graph}// namespace m1une#line 1 "graph/eulerian_trail.hpp"
#line 9 "graph/eulerian_trail.hpp"
#line 11 "graph/eulerian_trail.hpp"
namespacem1une{namespacegraph{structEulerianTrail{std::vector<int>vertices;std::vector<int>edge_ids;intedge_count()const{returnint(edge_ids.size());}boolis_circuit()const{returnvertices.empty()||vertices.front()==vertices.back();}};namespaceinternal{template<classT>std::optional<EulerianTrail>hierholzer(constGraph<T>&graph,intstart,intactive_edge_count){EulerianTrailresult;if(active_edge_count==0){if(start!=-1)result.vertices.push_back(start);returnresult;}assert(0<=start&&start<graph.size());std::vector<char>used(graph.edge_count(),false);std::vector<int>cursor(graph.size(),0);std::vector<int>vertex_stack(1,start);std::vector<int>incoming_edge_stack(1,-1);std::vector<int>reversed_vertices;std::vector<int>reversed_edges;reversed_vertices.reserve(active_edge_count+1);reversed_edges.reserve(active_edge_count);while(!vertex_stack.empty()){constintvertex=vertex_stack.back();while(cursor[vertex]<int(graph[vertex].size())){constEdge<T>&edge=graph[vertex][cursor[vertex]];if(edge.alive&&!used[edge.id])break;cursor[vertex]++;}if(cursor[vertex]<int(graph[vertex].size())){constEdge<T>&edge=graph[vertex][cursor[vertex]++];used[edge.id]=true;vertex_stack.push_back(edge.to);incoming_edge_stack.push_back(edge.id);continue;}reversed_vertices.push_back(vertex);constintincoming_edge=incoming_edge_stack.back();if(incoming_edge!=-1)reversed_edges.push_back(incoming_edge);vertex_stack.pop_back();incoming_edge_stack.pop_back();}if(int(reversed_edges.size())!=active_edge_count)returnstd::nullopt;std::reverse(reversed_vertices.begin(),reversed_vertices.end());std::reverse(reversed_edges.begin(),reversed_edges.end());result.vertices=std::move(reversed_vertices);result.edge_ids=std::move(reversed_edges);returnresult;}template<classT>std::vector<int>edge_incidence_count(constGraph<T>&graph){std::vector<int>count(graph.edge_count(),0);for(intvertex=0;vertex<graph.size();vertex++){for(constEdge<T>&edge:graph[vertex]){if(!edge.alive)continue;assert(0<=edge.id&&edge.id<graph.edge_count());count[edge.id]++;}}returncount;}}// namespace internaltemplate<classT>std::optional<EulerianTrail>directed_eulerian_trail(constGraph<T>&graph,intstart=-1){assert(start==-1||(0<=start&&start<graph.size()));constintn=graph.size();std::vector<int>incidence=internal::edge_incidence_count(graph);std::vector<int>in_degree(n,0);std::vector<int>out_degree(n,0);intactive_edge_count=0;for(intvertex=0;vertex<n;vertex++){for(constEdge<T>&edge:graph[vertex]){if(!edge.alive)continue;out_degree[vertex]++;in_degree[edge.to]++;}}for(intcount:incidence){if(count==0)continue;assert(count==1);active_edge_count++;}intrequired_start=-1;intrequired_end=-1;for(intvertex=0;vertex<n;vertex++){constintdifference=out_degree[vertex]-in_degree[vertex];if(difference==1){if(required_start!=-1)returnstd::nullopt;required_start=vertex;}elseif(difference==-1){if(required_end!=-1)returnstd::nullopt;required_end=vertex;}elseif(difference!=0){returnstd::nullopt;}}if((required_start==-1)!=(required_end==-1))returnstd::nullopt;intchosen_start=start;if(active_edge_count==0){if(chosen_start==-1&&n>0)chosen_start=0;returninternal::hierholzer(graph,chosen_start,0);}if(required_start!=-1){if(chosen_start!=-1&&chosen_start!=required_start)returnstd::nullopt;chosen_start=required_start;}elseif(chosen_start==-1){for(intvertex=0;vertex<n;vertex++){if(out_degree[vertex]>0){chosen_start=vertex;break;}}}elseif(out_degree[chosen_start]==0){returnstd::nullopt;}returninternal::hierholzer(graph,chosen_start,active_edge_count);}template<classT>std::optional<EulerianTrail>undirected_eulerian_trail(constGraph<T>&graph,intstart=-1){assert(start==-1||(0<=start&&start<graph.size()));constintn=graph.size();std::vector<int>incidence=internal::edge_incidence_count(graph);std::vector<int>degree(n,0);intactive_edge_count=0;for(intvertex=0;vertex<n;vertex++){for(constEdge<T>&edge:graph[vertex]){if(edge.alive)degree[vertex]++;}}for(intcount:incidence){if(count==0)continue;assert(count==2);active_edge_count++;}std::vector<int>odd;for(intvertex=0;vertex<n;vertex++){if(degree[vertex]&1)odd.push_back(vertex);}if(!odd.empty()&&odd.size()!=2)returnstd::nullopt;intchosen_start=start;if(active_edge_count==0){if(chosen_start==-1&&n>0)chosen_start=0;returninternal::hierholzer(graph,chosen_start,0);}if(odd.size()==2){if(chosen_start!=-1&&chosen_start!=odd[0]&&chosen_start!=odd[1]){returnstd::nullopt;}if(chosen_start==-1)chosen_start=odd[0];}elseif(chosen_start==-1){for(intvertex=0;vertex<n;vertex++){if(degree[vertex]>0){chosen_start=vertex;break;}}}elseif(degree[chosen_start]==0){returnstd::nullopt;}returninternal::hierholzer(graph,chosen_start,active_edge_count);}}// namespace graph}// namespace m1une#line 1 "graph/functional_graph.hpp"
#line 10 "graph/functional_graph.hpp"
namespacem1une{namespacegraph{structFunctionalGraph{intcomponent_count;std::vector<int>successor;std::vector<std::vector<int>>predecessors;std::vector<std::vector<int>>cycles;std::vector<int>component;std::vector<int>component_size;std::vector<int>cycle_entry;std::vector<int>cycle_position;std::vector<int>distance_to_cycle;private:std::vector<std::vector<int>>_up;voidcheck_vertex(intvertex)const{assert(0<=vertex&&vertex<size());}intadvance_before_cycle(intvertex,intsteps)const{assert(0<=steps&&steps<=distance_to_cycle[vertex]);intbit=0;while(steps>0){if(steps&1)vertex=_up[bit][vertex];steps>>=1;bit++;}returnvertex;}public:FunctionalGraph():component_count(0){}explicitFunctionalGraph(conststd::vector<int>&successor_){build(successor_);}voidbuild(conststd::vector<int>&successor_){successor=successor_;constintn=size();for(intto:successor)assert(0<=to&&to<n);component_count=0;predecessors.assign(n,{});cycles.clear();component.assign(n,-1);cycle_entry.assign(n,-1);cycle_position.assign(n,-1);distance_to_cycle.assign(n,-1);std::vector<int>indegree(n,0);for(intvertex=0;vertex<n;vertex++){predecessors[successor[vertex]].push_back(vertex);indegree[successor[vertex]]++;}std::queue<int>queue;std::vector<char>removed(n,false);for(intvertex=0;vertex<n;vertex++){if(indegree[vertex]==0)queue.push(vertex);}while(!queue.empty()){constintvertex=queue.front();queue.pop();removed[vertex]=true;constintto=successor[vertex];indegree[to]--;if(indegree[to]==0)queue.push(to);}for(intstart=0;start<n;start++){if(removed[start]||component[start]!=-1)continue;constintcomponent_id=int(cycles.size());std::vector<int>cycle;intvertex=start;do{constintposition=int(cycle.size());cycle.push_back(vertex);component[vertex]=component_id;cycle_entry[vertex]=vertex;cycle_position[vertex]=position;distance_to_cycle[vertex]=0;vertex=successor[vertex];}while(vertex!=start);cycles.push_back(std::move(cycle));}component_count=int(cycles.size());for(conststd::vector<int>&cycle:cycles){for(intvertex:cycle)queue.push(vertex);}while(!queue.empty()){constintvertex=queue.front();queue.pop();for(intfrom:predecessors[vertex]){if(component[from]!=-1)continue;component[from]=component[vertex];cycle_entry[from]=cycle_entry[vertex];cycle_position[from]=cycle_position[vertex];distance_to_cycle[from]=distance_to_cycle[vertex]+1;queue.push(from);}}component_size.assign(component_count,0);for(intcomponent_id:component)component_size[component_id]++;intlog=1;while((std::uint64_t(1)<<log)<=std::uint64_t(n))log++;_up.assign(log,successor);for(intbit=1;bit<log;bit++){for(intvertex=0;vertex<n;vertex++){_up[bit][vertex]=_up[bit-1][_up[bit-1][vertex]];}}}intsize()const{returnint(successor.size());}boolempty()const{returnsuccessor.empty();}boolsame_component(intfirst,intsecond)const{check_vertex(first);check_vertex(second);returncomponent[first]==component[second];}boolon_cycle(intvertex)const{check_vertex(vertex);returndistance_to_cycle[vertex]==0;}intcycle_size(intvertex)const{check_vertex(vertex);returnint(cycles[component[vertex]].size());}intorbit_size(intvertex)const{check_vertex(vertex);returndistance_to_cycle[vertex]+cycle_size(vertex);}intjump(intvertex,std::uint64_tsteps)const{check_vertex(vertex);constinttail_length=distance_to_cycle[vertex];if(steps<std::uint64_t(tail_length)){returnadvance_before_cycle(vertex,int(steps));}steps-=std::uint64_t(tail_length);constintentry=cycle_entry[vertex];constintlength=cycle_size(entry);constintoffset=int(steps%std::uint64_t(length));constintposition=(cycle_position[entry]+offset)%length;returncycles[component[vertex]][position];}longlongdistance(intfrom,intto)const{check_vertex(from);check_vertex(to);if(!same_component(from,to))return-1;if(!on_cycle(to)){if(distance_to_cycle[from]<distance_to_cycle[to])return-1;constintdifference=distance_to_cycle[from]-distance_to_cycle[to];returnadvance_before_cycle(from,difference)==to?difference:-1;}constintentry=cycle_entry[from];constintlength=cycle_size(from);intcycle_distance=cycle_position[to]-cycle_position[entry];if(cycle_distance<0)cycle_distance+=length;returnstatic_cast<longlong>(distance_to_cycle[from])+cycle_distance;}boolreachable(intfrom,intto)const{returndistance(from,to)!=-1;}std::vector<int>path(intfrom,intto)const{constlonglongpath_length=distance(from,to);if(path_length==-1)return{};std::vector<int>result;result.reserve(path_length+1);for(longlongstep=0;step<=path_length;step++){result.push_back(from);from=successor[from];}returnresult;}std::vector<int>orbit(intvertex)const{check_vertex(vertex);constintlength=orbit_size(vertex);std::vector<int>result;result.reserve(length);for(intstep=0;step<length;step++){result.push_back(vertex);vertex=successor[vertex];}returnresult;}std::uint64_tvisit_count(intfrom,intto,std::uint64_tstep_count)const{constlonglongfirst_visit=distance(from,to);if(first_visit==-1||std::uint64_t(first_visit)>=step_count){return0;}if(!on_cycle(to))return1;conststd::uint64_tremaining=step_count-1-std::uint64_t(first_visit);return1+remaining/std::uint64_t(cycle_size(to));}longlongfirst_meeting_time(intfirst,intsecond)const{check_vertex(first);check_vertex(second);if(!same_component(first,second))return-1;if(first==second)return0;constintfirst_depth=distance_to_cycle[first];constintsecond_depth=distance_to_cycle[second];if(first_depth==second_depth&&cycle_entry[first]==cycle_entry[second]){intelapsed=0;for(intbit=int(_up.size())-1;bit>=0;bit--){constintsteps=1<<bit;if(first_depth-elapsed<steps)continue;constintnext_first=_up[bit][first];constintnext_second=_up[bit][second];if(next_first==next_second)continue;first=next_first;second=next_second;elapsed+=steps;}returnelapsed+1;}constintlength=cycle_size(first);intfirst_phase=cycle_position[first]-first_depth%length;intsecond_phase=cycle_position[second]-second_depth%length;if(first_phase<0)first_phase+=length;if(second_phase<0)second_phase+=length;if(first_phase!=second_phase)return-1;returnstd::max(first_depth,second_depth);}intfirst_meeting_vertex(intfirst,intsecond)const{constlonglongtime=first_meeting_time(first,second);if(time==-1)return-1;returnjump(first,std::uint64_t(time));}};}// namespace graph}// namespace m1une#line 1 "graph/incremental_scc.hpp"
#line 9 "graph/incremental_scc.hpp"
#line 11 "graph/incremental_scc.hpp"
namespacem1une{namespacegraph{namespaceincremental_scc_detail{structEdgeEvent{intid;intfrom;intto;};inlinestd::vector<int>component_ids(intvertex_count,conststd::vector<EdgeEvent>&edges,inttime){std::vector<int>begin(vertex_count+1,0);std::vector<int>reverse_begin(vertex_count+1,0);intedge_count=0;for(constEdgeEvent&edge:edges){if(edge.id>=time)continue;begin[edge.from+1]++;reverse_begin[edge.to+1]++;edge_count++;}for(intvertex=0;vertex<vertex_count;vertex++){begin[vertex+1]+=begin[vertex];reverse_begin[vertex+1]+=reverse_begin[vertex];}std::vector<int>adjacency(edge_count);std::vector<int>reverse_adjacency(edge_count);std::vector<int>cursor=begin;std::vector<int>reverse_cursor=reverse_begin;for(constEdgeEvent&edge:edges){if(edge.id>=time)continue;adjacency[cursor[edge.from]++]=edge.to;reverse_adjacency[reverse_cursor[edge.to]++]=edge.from;}std::vector<int>().swap(cursor);std::vector<int>().swap(reverse_cursor);std::vector<char>visited(vertex_count,false);std::vector<int>next_position(begin.begin(),begin.end()-1);std::vector<int>order;order.reserve(vertex_count);std::vector<int>stack;for(intstart=0;start<vertex_count;start++){if(visited[start])continue;visited[start]=true;stack.push_back(start);while(!stack.empty()){constintvertex=stack.back();int&position=next_position[vertex];if(position<begin[vertex+1]){constintto=adjacency[position++];if(!visited[to]){visited[to]=true;stack.push_back(to);}}else{order.push_back(vertex);stack.pop_back();}}}std::vector<int>component(vertex_count,-1);intcomponent_count=0;for(autoiterator=order.rbegin();iterator!=order.rend();++iterator){constintstart=*iterator;if(component[start]!=-1)continue;component[start]=component_count;stack.push_back(start);while(!stack.empty()){constintvertex=stack.back();stack.pop_back();for(intposition=reverse_begin[vertex];position<reverse_begin[vertex+1];position++){constintto=reverse_adjacency[position];if(component[to]!=-1)continue;component[to]=component_count;stack.push_back(to);}}component_count++;}returncomponent;}}// namespace incremental_scc_detail// For every directed edge e, returns the first time t after e is inserted such// that its endpoints are in the same SCC. At time t, edges with IDs less than// t have been inserted. edge_count() + 1 means this never happens.template<classT>std::vector<int>incremental_scc(constGraph<T>&graph){usingincremental_scc_detail::EdgeEvent;usingincremental_scc_detail::component_ids;constintvertex_count=graph.size();constintedge_count=graph.edge_count();constintnever=edge_count+1;std::vector<int>merge_time(edge_count,never);if(edge_count==0)returnmerge_time;std::vector<EdgeEvent>edges_by_id(edge_count);std::vector<char>initialized(edge_count,false);for(intvertex=0;vertex<vertex_count;vertex++){for(constEdge<T>&edge:graph[vertex]){assert(0<=edge.id&&edge.id<edge_count);assert(!initialized[edge.id]);if(initialized[edge.id])continue;initialized[edge.id]=true;edges_by_id[edge.id]=EdgeEvent{edge.id,edge.from,edge.to};}}std::vector<EdgeEvent>events;events.reserve(edge_count);for(intedge_id=0;edge_id<edge_count;edge_id++){assert(initialized[edge_id]);if(graph.is_edge_alive(edge_id)){events.push_back(edges_by_id[edge_id]);}}std::vector<EdgeEvent>().swap(edges_by_id);std::vector<char>().swap(initialized);std::vector<int>new_index(vertex_count,-1);autodivide=[&](auto&&self,std::vector<EdgeEvent>current,intleft,intright)->void{if(current.empty()||right==left+1)return;constintmiddle=left+(right-left)/2;std::vector<int>touched;touched.reserve(std::min(std::size_t(vertex_count),current.size()*2));intcompressed_count=0;for(constEdgeEvent&edge:current){if(new_index[edge.from]==-1){new_index[edge.from]=compressed_count++;touched.push_back(edge.from);}if(new_index[edge.to]==-1){new_index[edge.to]=compressed_count++;touched.push_back(edge.to);}}for(EdgeEvent&edge:current){edge.from=new_index[edge.from];edge.to=new_index[edge.to];}for(intvertex:touched)new_index[vertex]=-1;std::vector<EdgeEvent>earlier;std::vector<EdgeEvent>later;earlier.reserve(current.size()/2);later.reserve(current.size()/2);{std::vector<int>component=component_ids(compressed_count,current,middle);for(constEdgeEvent&edge:current){constintfrom_component=component[edge.from];constintto_component=component[edge.to];if(edge.id<middle&&from_component==to_component){merge_time[edge.id]=std::min(merge_time[edge.id],middle);earlier.push_back(edge);}else{later.push_back(EdgeEvent{edge.id,from_component,to_component});}}}std::vector<EdgeEvent>().swap(current);self(self,std::move(earlier),left,middle);self(self,std::move(later),middle,right);};divide(divide,std::move(events),0,edge_count+1);returnmerge_time;}}// namespace graph}// namespace m1une#line 1 "graph/matrix_tree_theorem.hpp"
#line 7 "graph/matrix_tree_theorem.hpp"
#line 1 "math/matrix/linear_algebra.hpp"
#line 7 "math/matrix/linear_algebra.hpp"
#line 1 "math/matrix/matrix.hpp"
#line 9 "math/matrix/matrix.hpp"
namespacem1une{namespacematrix{template<classT>classMatrix{private:int_rows;int_cols;std::vector<T>_data;staticstd::size_tstorage_size(introws,intcols){assert(rows>=0);assert(cols>=0);returnstd::size_t(rows)*std::size_t(cols);}public:usingvalue_type=T;Matrix():_rows(0),_cols(0){}Matrix(introws,intcols,constT&value=T()):_rows(rows),_cols(cols),_data(storage_size(rows,cols),value){}Matrix(introws,intcols,std::vector<T>values):_rows(rows),_cols(cols),_data(std::move(values)){assert(rows>=0);assert(cols>=0);assert(_data.size()==std::size_t(rows)*std::size_t(cols));}explicitMatrix(conststd::vector<std::vector<T>>&values):_rows(int(values.size())),_cols(values.empty()?0:int(values[0].size())),_data(storage_size(_rows,_cols)){for(introw=0;row<_rows;row++){assert(int(values[std::size_t(row)].size())==_cols);for(intcol=0;col<_cols;col++){(*this)[row][col]=values[std::size_t(row)][std::size_t(col)];}}}introws()const{return_rows;}intcols()const{return_cols;}boolempty()const{return_rows==0||_cols==0;}std::vector<T>&data(){return_data;}conststd::vector<T>&data()const{return_data;}T*operator[](introw){assert(0<=row&&row<_rows);return_data.data()+std::size_t(row)*std::size_t(_cols);}constT*operator[](introw)const{assert(0<=row&&row<_rows);return_data.data()+std::size_t(row)*std::size_t(_cols);}T&operator()(introw,intcol){assert(0<=col&&col<_cols);return(*this)[row][col];}constT&operator()(introw,intcol)const{assert(0<=col&&col<_cols);return(*this)[row][col];}staticMatrixidentity(intsize){assert(size>=0);Matrixresult(size,size);for(inti=0;i<size;i++)result[i][i]=T(1);returnresult;}Matrixtransposed()const{Matrixresult(_cols,_rows);for(introw=0;row<_rows;row++){for(intcol=0;col<_cols;col++){result[col][row]=(*this)[row][col];}}returnresult;}voidswap_rows(intfirst,intsecond){assert(0<=first&&first<_rows);assert(0<=second&&second<_rows);if(first==second)return;for(intcol=0;col<_cols;col++){std::swap((*this)[first][col],(*this)[second][col]);}}Matrix&operator+=(constMatrix&rhs){assert(_rows==rhs._rows&&_cols==rhs._cols);for(std::size_ti=0;i<_data.size();i++)_data[i]+=rhs._data[i];return*this;}Matrix&operator-=(constMatrix&rhs){assert(_rows==rhs._rows&&_cols==rhs._cols);for(std::size_ti=0;i<_data.size();i++)_data[i]-=rhs._data[i];return*this;}Matrix&operator*=(constT&scalar){for(T&value:_data)value*=scalar;return*this;}Matrix&operator/=(constT&scalar){for(T&value:_data)value/=scalar;return*this;}Matrix&operator*=(constMatrix&rhs){return*this=*this*rhs;}Matrixoperator+()const{return*this;}Matrixoperator-()const{Matrixresult=*this;for(T&value:result._data)value=T()-value;returnresult;}friendMatrixoperator+(Matrixlhs,constMatrix&rhs){returnlhs+=rhs;}friendMatrixoperator-(Matrixlhs,constMatrix&rhs){returnlhs-=rhs;}friendMatrixoperator*(Matrixlhs,constT&rhs){returnlhs*=rhs;}friendMatrixoperator*(constT&lhs,Matrixrhs){returnrhs*=lhs;}friendMatrixoperator/(Matrixlhs,constT&rhs){returnlhs/=rhs;}friendMatrixoperator*(constMatrix&lhs,constMatrix&rhs){assert(lhs._cols==rhs._rows);Matrixresult(lhs._rows,rhs._cols);for(introw=0;row<lhs._rows;row++){T*output=result[row];for(intmiddle=0;middle<lhs._cols;middle++){constTcoefficient=lhs[row][middle];if(coefficient==T())continue;constT*input=rhs[middle];for(intcol=0;col<rhs._cols;col++){output[col]+=coefficient*input[col];}}}returnresult;}friendstd::vector<T>operator*(constMatrix&lhs,conststd::vector<T>&rhs){assert(lhs._cols==int(rhs.size()));std::vector<T>result(std::size_t(lhs._rows));for(introw=0;row<lhs._rows;row++){Tvalue=T();for(intcol=0;col<lhs._cols;col++){value+=lhs[row][col]*rhs[std::size_t(col)];}result[std::size_t(row)]=value;}returnresult;}friendstd::vector<T>operator*(conststd::vector<T>&lhs,constMatrix&rhs){assert(int(lhs.size())==rhs._rows);std::vector<T>result(std::size_t(rhs._cols));for(introw=0;row<rhs._rows;row++){if(lhs[std::size_t(row)]==T())continue;for(intcol=0;col<rhs._cols;col++){result[std::size_t(col)]+=lhs[std::size_t(row)]*rhs[row][col];}}returnresult;}booloperator==(constMatrix&rhs)const{return_rows==rhs._rows&&_cols==rhs._cols&&_data==rhs._data;}booloperator!=(constMatrix&rhs)const{return!(*this==rhs);}Matrixpow(std::uint64_texponent)const{assert(_rows==_cols);Matrixresult=identity(_rows);Matrixbase=*this;while(exponent>0){if(exponent&1)result*=base;exponent>>=1;if(exponent>0)base*=base;}returnresult;}};}// namespace matrix}// namespace m1une#line 9 "math/matrix/linear_algebra.hpp"
namespacem1une{namespacematrix{template<classT>constexprTdefault_epsilon(){ifconstexpr(std::is_floating_point_v<T>){returnT(1e-10);}else{returnT();}}namespacedetail{template<classT>Tmatrix_abs(Tvalue){returnvalue<T()?T()-value:value;}template<classT>boolis_zero(constT&value,constT&eps){ifconstexpr(std::is_floating_point_v<T>){returnmatrix_abs(value)<=eps;}else{(void)eps;returnvalue==T();}}template<classT>intchoose_pivot(constMatrix<T>&matrix,intfirst_row,intcol,constT&eps){intpivot=-1;ifconstexpr(std::is_floating_point_v<T>){for(introw=first_row;row<matrix.rows();row++){if(is_zero(matrix[row][col],eps))continue;if(pivot==-1||matrix_abs(matrix[pivot][col])<matrix_abs(matrix[row][col])){pivot=row;}}}else{for(introw=first_row;row<matrix.rows();row++){if(!is_zero(matrix[row][col],eps)){pivot=row;break;}}}returnpivot;}template<classT>std::vector<int>row_reduce(Matrix<T>&matrix,intpivot_col_limit,constT&eps,boolreduced){std::vector<int>pivot_columns;intpivot_row=0;for(intcol=0;col<pivot_col_limit&&pivot_row<matrix.rows();col++){intpivot=choose_pivot(matrix,pivot_row,col,eps);if(pivot==-1)continue;matrix.swap_rows(pivot_row,pivot);constTpivot_value=matrix[pivot_row][col];if(reduced){for(intj=col;j<matrix.cols();j++)matrix[pivot_row][j]/=pivot_value;}constintfirst_row=reduced?0:pivot_row+1;for(introw=first_row;row<matrix.rows();row++){if(row==pivot_row||is_zero(matrix[row][col],eps))continue;Tfactor=matrix[row][col];if(!reduced)factor/=pivot_value;matrix[row][col]=T();for(intj=col+1;j<matrix.cols();j++){matrix[row][j]-=factor*matrix[pivot_row][j];}}pivot_columns.push_back(col);pivot_row++;}ifconstexpr(std::is_floating_point_v<T>){for(T&value:matrix.data()){if(is_zero(value,eps))value=T();}}returnpivot_columns;}}// namespace detailtemplate<classT>structRowReduction{Matrix<T>matrix;std::vector<int>pivot_columns;intrank()const{returnint(pivot_columns.size());}};template<classT>RowReduction<T>reduced_row_echelon_form(Matrix<T>matrix,Teps=default_epsilon<T>()){RowReduction<T>result;result.pivot_columns=detail::row_reduce(matrix,matrix.cols(),eps,true);result.matrix=std::move(matrix);returnresult;}template<classT>intmatrix_rank(Matrix<T>matrix,Teps=default_epsilon<T>()){returnint(detail::row_reduce(matrix,matrix.cols(),eps,false).size());}template<classT>Tdeterminant(Matrix<T>matrix,Teps=default_epsilon<T>()){assert(matrix.rows()==matrix.cols());constintsize=matrix.rows();Tresult=T(1);boolnegate=false;for(intcol=0;col<size;col++){intpivot=detail::choose_pivot(matrix,col,col,eps);if(pivot==-1)returnT();if(pivot!=col){matrix.swap_rows(pivot,col);negate=!negate;}constTpivot_value=matrix[col][col];result*=pivot_value;for(introw=col+1;row<size;row++){if(detail::is_zero(matrix[row][col],eps))continue;constTfactor=matrix[row][col]/pivot_value;matrix[row][col]=T();for(intj=col+1;j<size;j++){matrix[row][j]-=factor*matrix[col][j];}}}returnnegate?T()-result:result;}template<classT>std::optional<Matrix<T>>inverse(constMatrix<T>&matrix,Teps=default_epsilon<T>()){assert(matrix.rows()==matrix.cols());constintsize=matrix.rows();Matrix<T>augmented(size,size*2);for(introw=0;row<size;row++){for(intcol=0;col<size;col++){augmented[row][col]=matrix[row][col];}augmented[row][size+row]=T(1);}conststd::vector<int>pivots=detail::row_reduce(augmented,size,eps,true);if(int(pivots.size())!=size)returnstd::nullopt;Matrix<T>result(size,size);for(introw=0;row<size;row++){for(intcol=0;col<size;col++){result[row][col]=augmented[row][size+col];}}returnresult;}template<classT>structLinearSystemResult{boolconsistent=false;std::vector<T>particular_solution;std::vector<std::vector<T>>nullspace_basis;std::vector<int>pivot_columns;intrank()const{returnint(pivot_columns.size());}intnullity()const{returnconsistent?int(nullspace_basis.size()):0;}boolhas_unique_solution()const{returnconsistent&&nullspace_basis.empty();}};template<classT>LinearSystemResult<T>solve_linear_system(constMatrix<T>&coefficients,conststd::vector<T>&constants,Teps=default_epsilon<T>()){assert(coefficients.rows()==int(constants.size()));constintequation_count=coefficients.rows();constintvariable_count=coefficients.cols();Matrix<T>augmented(equation_count,variable_count+1);for(introw=0;row<equation_count;row++){for(intcol=0;col<variable_count;col++){augmented[row][col]=coefficients[row][col];}augmented[row][variable_count]=constants[std::size_t(row)];}LinearSystemResult<T>result;result.pivot_columns=detail::row_reduce(augmented,variable_count,eps,true);for(introw=result.rank();row<equation_count;row++){boolzero_left=true;for(intcol=0;col<variable_count;col++){if(!detail::is_zero(augmented[row][col],eps)){zero_left=false;break;}}if(zero_left&&!detail::is_zero(augmented[row][variable_count],eps)){returnresult;}}result.consistent=true;result.particular_solution.assign(std::size_t(variable_count),T());std::vector<bool>is_pivot(std::size_t(variable_count),false);for(introw=0;row<result.rank();row++){constintcol=result.pivot_columns[std::size_t(row)];is_pivot[std::size_t(col)]=true;result.particular_solution[std::size_t(col)]=augmented[row][variable_count];}for(intfree_col=0;free_col<variable_count;free_col++){if(is_pivot[std::size_t(free_col)])continue;std::vector<T>direction(static_cast<std::size_t>(variable_count));direction[std::size_t(free_col)]=T(1);for(introw=0;row<result.rank();row++){constintpivot_col=result.pivot_columns[std::size_t(row)];direction[std::size_t(pivot_col)]=T()-augmented[row][free_col];}result.nullspace_basis.push_back(std::move(direction));}returnresult;}}// namespace matrix}// namespace m1une#line 10 "graph/matrix_tree_theorem.hpp"
namespacem1une{namespacegraph{namespacematrix_tree_detail{inlineintminor_index(intvertex,intremoved){assert(vertex!=removed);returnvertex<removed?vertex:vertex-1;}template<classWeight>voidassert_edge_incidence(constGraph<Weight>&graph,intexpected){#ifndef NDEBUG
std::vector<int>incidence(graph.edge_count(),0);for(intvertex=0;vertex<graph.size();vertex++){for(constEdge<Weight>&edge:graph[vertex]){if(!edge.alive)continue;assert(0<=edge.id&&edge.id<graph.edge_count());incidence[edge.id]++;}}for(intcount:incidence){if(count!=0)assert(count==expected);}#else
(void)graph;(void)expected;#endif
}template<classField,classWeight>Fieldcount_arborescences(constGraph<Weight>&graph,introot,booloutward){constintn=graph.size();assert(0<=root&&root<n);assert_edge_incidence(graph,1);matrix::Matrix<Field>minor(n-1,n-1);for(intvertex=0;vertex<n;vertex++){for(constEdge<Weight>&edge:graph[vertex]){if(!edge.alive||edge.from==edge.to)continue;constintrow=outward?edge.to:edge.from;constintcol=outward?edge.from:edge.to;if(row==root)continue;constFieldweight(edge.cost);constintreduced_row=minor_index(row,root);minor[reduced_row][reduced_row]+=weight;if(col!=root){minor[reduced_row][minor_index(col,root)]-=weight;}}}returnmatrix::determinant(std::move(minor));}}// namespace matrix_tree_detail// Returns the total weight of all undirected spanning trees. The weight of a// tree is the product of its edge costs.template<classField,classWeight>Fieldcount_spanning_trees(constGraph<Weight>&graph){constintn=graph.size();assert(n>0);matrix_tree_detail::assert_edge_incidence(graph,2);constintremoved=n-1;matrix::Matrix<Field>minor(n-1,n-1);for(intvertex=0;vertex<n;vertex++){for(constEdge<Weight>&edge:graph[vertex]){if(!edge.alive||edge.from>=edge.to)continue;constintfrom=edge.from;constintto=edge.to;constFieldweight(edge.cost);if(from!=removed){constintreduced_from=matrix_tree_detail::minor_index(from,removed);minor[reduced_from][reduced_from]+=weight;}if(to!=removed){constintreduced_to=matrix_tree_detail::minor_index(to,removed);minor[reduced_to][reduced_to]+=weight;}if(from!=removed&&to!=removed){constintreduced_from=matrix_tree_detail::minor_index(from,removed);constintreduced_to=matrix_tree_detail::minor_index(to,removed);minor[reduced_from][reduced_to]-=weight;minor[reduced_to][reduced_from]-=weight;}}}returnmatrix::determinant(std::move(minor));}// Counts directed spanning trees whose edges point away from root, so every// vertex is reachable from root.template<classField,classWeight>Fieldcount_out_arborescences(constGraph<Weight>&graph,introot){returnmatrix_tree_detail::count_arborescences<Field>(graph,root,true);}// Counts directed spanning trees whose edges point toward root, so root is// reachable from every vertex.template<classField,classWeight>Fieldcount_in_arborescences(constGraph<Weight>&graph,introot){returnmatrix_tree_detail::count_arborescences<Field>(graph,root,false);}}// namespace graph}// namespace m1une#line 1 "graph/scc.hpp"
#line 9 "graph/scc.hpp"
#line 11 "graph/scc.hpp"
namespacem1une{namespacegraph{structSccResult{intcount;std::vector<int>comp;std::vector<std::vector<int>>groups;boolsame(intu,intv)const{assert(0<=u&&u<int(comp.size()));assert(0<=v&&v<int(comp.size()));returncomp[u]==comp[v];}template<classT>Graph<int>dag(constGraph<T>&g)const{std::vector<std::pair<int,int>>edges;for(intv=0;v<g.size();v++){for(constauto&e:g[v]){if(!e.alive)continue;inta=comp[e.from],b=comp[e.to];if(a!=b)edges.emplace_back(a,b);}}std::sort(edges.begin(),edges.end());edges.erase(std::unique(edges.begin(),edges.end()),edges.end());Graph<int>result(count);for(auto[a,b]:edges)result.add_directed_edge(a,b);returnresult;}};template<classT>SccResultstrongly_connected_components(constGraph<T>&g){constintn=g.size();std::vector<std::vector<int>>reverse_graph(n);for(intvertex=0;vertex<n;vertex++){for(constauto&edge:g[vertex]){if(edge.alive)reverse_graph[edge.to].push_back(vertex);}}std::vector<char>seen(n,false);std::vector<int>order;order.reserve(n);std::vector<std::pair<int,std::size_t>>dfs_stack;for(intstart=0;start<n;start++){if(seen[start])continue;seen[start]=true;dfs_stack.emplace_back(start,0);while(!dfs_stack.empty()){intvertex=dfs_stack.back().first;std::size_t&edge_index=dfs_stack.back().second;while(edge_index<g[vertex].size()&&!g[vertex][edge_index].alive){edge_index++;}if(edge_index==g[vertex].size()){order.push_back(vertex);dfs_stack.pop_back();continue;}constintto=g[vertex][edge_index++].to;if(!seen[to]){seen[to]=true;dfs_stack.emplace_back(to,0);}}}std::vector<int>comp(n,-1);std::vector<std::vector<int>>groups;std::vector<int>stack;for(autoiterator=order.rbegin();iterator!=order.rend();++iterator){constintstart=*iterator;if(comp[start]!=-1)continue;constintcomponent=int(groups.size());groups.emplace_back();comp[start]=component;stack.push_back(start);while(!stack.empty()){constintvertex=stack.back();stack.pop_back();groups.back().push_back(vertex);for(intto:reverse_graph[vertex]){if(comp[to]!=-1)continue;comp[to]=component;stack.push_back(to);}}}returnSccResult{int(groups.size()),std::move(comp),std::move(groups)};}}// namespace graph}// namespace m1une#line 1 "graph/shortest_path.hpp"
#line 1 "graph/bellman_ford.hpp"
#line 9 "graph/bellman_ford.hpp"
#line 11 "graph/bellman_ford.hpp"
namespacem1une{namespacegraph{template<classT>structBellmanFordResult{std::vector<T>dist;std::vector<int>parent;std::vector<int>parent_edge;std::vector<bool>negative;Tinf;boolhas_negative_cycle;boolreachable(intv)const{assert(0<=v&&v<int(dist.size()));returndist[v]!=inf;}boolaffected_by_negative_cycle(intv)const{assert(0<=v&&v<int(negative.size()));returnnegative[v];}std::vector<int>path(intt)const{assert(reachable(t));assert(!affected_by_negative_cycle(t));std::vector<int>result;for(intv=t;v!=-1;v=parent[v])result.push_back(v);std::reverse(result.begin(),result.end());returnresult;}};template<classT>BellmanFordResult<T>bellman_ford(constGraph<T>&g,conststd::vector<int>&sources,Tinf=std::numeric_limits<T>::max()/T(4)){intn=g.size();BellmanFordResult<T>result;result.dist.assign(n,inf);result.parent.assign(n,-1);result.parent_edge.assign(n,-1);result.negative.assign(n,false);result.inf=inf;result.has_negative_cycle=false;for(ints:sources){assert(0<=s&&s<n);result.dist[s]=T(0);}std::vector<int>relaxed_vertices;for(intiter=0;iter<n;iter++){boolupdated=false;for(intv=0;v<n;v++){if(result.dist[v]==inf)continue;for(constauto&e:g[v]){if(!e.alive)continue;Tnd=result.dist[v]+e.cost;if(result.dist[e.to]<=nd)continue;result.dist[e.to]=nd;result.parent[e.to]=v;result.parent_edge[e.to]=e.id;updated=true;if(iter==n-1)relaxed_vertices.push_back(e.to);}}if(!updated)break;}std::queue<int>que;for(intv:relaxed_vertices){if(result.negative[v])continue;result.negative[v]=true;que.push(v);}while(!que.empty()){intv=que.front();que.pop();for(constauto&e:g[v]){if(!e.alive)continue;if(result.negative[e.to])continue;result.negative[e.to]=true;que.push(e.to);}}for(boolx:result.negative)result.has_negative_cycle=result.has_negative_cycle||x;returnresult;}template<classT>BellmanFordResult<T>bellman_ford(constGraph<T>&g,ints,Tinf=std::numeric_limits<T>::max()/T(4)){returnbellman_ford(g,std::vector<int>{s},inf);}}// namespace graph}// namespace m1une#line 1 "graph/bfs.hpp"
#line 11 "graph/bfs.hpp"
#line 13 "graph/bfs.hpp"
namespacem1une{namespacegraph{structBfsResult{std::vector<int>dist;std::vector<int>parent;std::vector<int>parent_edge;boolreachable(intv)const{assert(0<=v&&v<int(dist.size()));returndist[v]!=-1;}std::vector<int>path(intt)const{assert(reachable(t));std::vector<int>result;for(intv=t;v!=-1;v=parent[v])result.push_back(v);std::reverse(result.begin(),result.end());returnresult;}};namespacebfs_detail{template<classCallback>conceptBfsCallback=std::invocable<Callback&,int,int>||std::invocable<Callback&,int>;template<BfsCallbackCallback>voidinvoke_callback(Callback&callback,intvertex,intparent){ifconstexpr(std::invocable<Callback&,int,int>){std::invoke(callback,vertex,parent);}else{std::invoke(callback,vertex);}}template<classT,classCallback>BfsResultrun_bfs(constGraph<T>&g,conststd::vector<int>&sources,Callback&callback){intn=g.size();BfsResultresult;result.dist.assign(n,-1);result.parent.assign(n,-1);result.parent_edge.assign(n,-1);std::queue<int>que;for(ints:sources){assert(0<=s&&s<n);if(result.dist[s]!=-1)continue;result.dist[s]=0;invoke_callback(callback,s,-1);que.push(s);}while(!que.empty()){intv=que.front();que.pop();for(constauto&e:g[v]){if(!e.alive)continue;if(result.dist[e.to]!=-1)continue;result.dist[e.to]=result.dist[v]+1;result.parent[e.to]=v;result.parent_edge[e.to]=e.id;invoke_callback(callback,e.to,v);que.push(e.to);}}returnresult;}}// namespace bfs_detailtemplate<classT>BfsResultbfs(constGraph<T>&g,conststd::vector<int>&sources){autocallback=[](int){};returnbfs_detail::run_bfs(g,sources,callback);}template<classT>BfsResultbfs(constGraph<T>&g,ints){returnbfs(g,std::vector<int>{s});}template<classT,classCallback>requiresbfs_detail::BfsCallback<Callback>BfsResultbfs(constGraph<T>&g,conststd::vector<int>&sources,Callback&&callback){returnbfs_detail::run_bfs(g,sources,callback);}template<classT,classCallback>requiresbfs_detail::BfsCallback<Callback>BfsResultbfs(constGraph<T>&g,intsource,Callback&&callback){returnbfs(g,std::vector<int>{source},std::forward<Callback>(callback));}}// namespace graph}// namespace m1une#line 1 "graph/cow_game.hpp"
#line 10 "graph/cow_game.hpp"
namespacem1une{namespacegraph{template<classT>structCowGameConstraint{inta;intb;Tupper_bound;};template<classT>structCowGameSolution{boolfeasible=false;std::vector<T>value;boolis_feasible()const{returnfeasible;}};template<classT>structCowGameUpperBounds{boolfeasible;std::vector<T>upper_bound;Tinf;boolis_feasible()const{returnfeasible;}boolbounded(intvariable)const{assert(0<=variable&&variable<int(upper_bound.size()));returnfeasible&&upper_bound[variable]!=inf;}};template<classT>structCowGameDifferenceBounds{boolfeasible;std::optional<T>lower_bound;std::optional<T>upper_bound;boolis_feasible()const{returnfeasible;}boolbounded_below()const{returnfeasible&&lower_bound.has_value();}boolbounded_above()const{returnfeasible&&upper_bound.has_value();}};template<classT>classCowGame{static_assert(std::is_arithmetic_v<T>&&std::is_signed_v<T>);structRelaxationResult{boolhas_negative_cycle;std::vector<T>dist;};int_n;std::vector<CowGameConstraint<T>>_constraints;std::vector<std::vector<int>>_outgoing_constraints;bool_has_negative_upper_bound=false;mutablebool_solution_cached=false;mutableCowGameSolution<T>_cached_solution;voidassert_variable(intvariable)const{(void)variable;assert(0<=variable&&variable<_n);}Tnegate(Tvalue)const{assert(value!=std::numeric_limits<T>::lowest());return-value;}RelaxationResultcheck_feasibility()const{std::vector<T>dist(_n,T());for(intiteration=0;iteration<_n;iteration++){boolupdated=false;for(constauto&constraint:_constraints){Tcandidate=dist[constraint.b]+constraint.upper_bound;if(dist[constraint.a]<=candidate)continue;dist[constraint.a]=candidate;updated=true;if(iteration==_n-1)returnRelaxationResult{true,std::move(dist)};}if(!updated)break;}returnRelaxationResult{false,std::move(dist)};}std::vector<T>shortest_paths(intsource,Tinf)const{constauto&potential=_cached_solution.value;std::vector<T>dist(_n,inf);std::vector<int>heap;// -1 is unseen, -2 is fixed, and every other value is a heap index.std::vector<int>position(_n,-1);heap.reserve(_n);autoswap_heap=[&](inti,intj){std::swap(heap[i],heap[j]);position[heap[i]]=i;position[heap[j]]=j;};autosift_up=[&](inti){while(i>0){intparent=(i-1)/2;if(dist[heap[parent]]<=dist[heap[i]])break;swap_heap(parent,i);i=parent;}};autosift_down=[&](inti){while(2*i+1<int(heap.size())){intchild=2*i+1;if(child+1<int(heap.size())&&dist[heap[child+1]]<dist[heap[child]]){child++;}if(dist[heap[i]]<=dist[heap[child]])break;swap_heap(i,child);i=child;}};dist[source]=T();position[source]=0;heap.push_back(source);while(!heap.empty()){intb=heap[0];position[b]=-2;intlast=heap.back();heap.pop_back();if(!heap.empty()){heap[0]=last;position[last]=0;sift_down(0);}for(intid:_outgoing_constraints[b]){constauto&constraint=_constraints[id];Tcost=constraint.upper_bound+potential[b]-potential[constraint.a];assert(cost>=T());Tcandidate=dist[b]+cost;if(dist[constraint.a]<=candidate)continue;dist[constraint.a]=candidate;assert(position[constraint.a]!=-2);if(position[constraint.a]==-1){position[constraint.a]=int(heap.size());heap.push_back(constraint.a);}sift_up(position[constraint.a]);}}for(intv=0;v<_n;v++){if(dist[v]==inf)continue;dist[v]=dist[v]-potential[source]+potential[v];}returndist;}public:CowGame():CowGame(0){}explicitCowGame(intvariable_count):_n(variable_count),_outgoing_constraints(variable_count<0?0:variable_count){assert(variable_count>=0);}intsize()const{return_n;}intconstraint_count()const{returnint(_constraints.size());}constCowGameConstraint<T>&get_constraint(intid)const{assert(0<=id&&id<int(_constraints.size()));return_constraints[id];}conststd::vector<CowGameConstraint<T>>&constraints()const{return_constraints;}boolcan_use_dijkstra()const{return!_has_negative_upper_bound||(_solution_cached&&_cached_solution.feasible);}intadd_upper_bound(inta,intb,Tupper_bound){assert_variable(a);assert_variable(b);intid=int(_constraints.size());_constraints.push_back(CowGameConstraint<T>{a,b,upper_bound});_outgoing_constraints[b].push_back(id);_has_negative_upper_bound=_has_negative_upper_bound||upper_bound<T();_solution_cached=false;returnid;}intadd_constraint(inta,intb,Tupper_bound){returnadd_upper_bound(a,b,upper_bound);}intadd_lower_bound(inta,intb,Tlower_bound){returnadd_upper_bound(b,a,negate(lower_bound));}voidadd_bounds(inta,intb,Tlower_bound,Tupper_bound){assert(lower_bound<=upper_bound);add_lower_bound(a,b,lower_bound);add_upper_bound(a,b,upper_bound);}voidadd_equality(inta,intb,Tdifference){add_bounds(a,b,difference,difference);}CowGameSolution<T>solve()const{if(_solution_cached)return_cached_solution;_cached_solution.feasible=true;_cached_solution.value.assign(_n,T());if(_has_negative_upper_bound){autoresult=check_feasibility();_cached_solution.feasible=!result.has_negative_cycle;_cached_solution.value.clear();if(_cached_solution.feasible){_cached_solution.value=std::move(result.dist);}}_solution_cached=true;return_cached_solution;}boolis_feasible()const{if(!_solution_cached)(void)solve();return_cached_solution.feasible;}CowGameUpperBounds<T>tightest_upper_bounds(intsource)const{assert_variable(source);Tinf=std::numeric_limits<T>::max()/T(4);CowGameUpperBounds<T>result;result.feasible=is_feasible();result.inf=inf;result.upper_bound.assign(_n,inf);if(!result.feasible)returnresult;result.upper_bound=shortest_paths(source,inf);returnresult;}CowGameDifferenceBounds<T>difference_bounds(inta,intb)const{assert_variable(a);assert_variable(b);Tinf=std::numeric_limits<T>::max()/T(4);CowGameDifferenceBounds<T>result;result.feasible=is_feasible();if(!result.feasible)returnresult;autoupper=shortest_paths(b,inf);if(upper[a]!=inf)result.upper_bound=upper[a];autolower=shortest_paths(a,inf);if(lower[b]!=inf)result.lower_bound=negate(lower[b]);returnresult;}};template<classT>usingDifferenceConstraints=CowGame<T>;}// namespace graph}// namespace m1une#line 1 "graph/dijkstra.hpp"
#line 8 "graph/dijkstra.hpp"
#line 10 "graph/dijkstra.hpp"
namespacem1une{namespacegraph{template<classT>structDijkstraResult{std::vector<T>dist;std::vector<char>reached;std::vector<int>parent;std::vector<int>parent_edge;Tinf=T();boolreachable(intv)const{assert(0<=v&&v<int(dist.size()));returnreached[v];}std::vector<int>path(intt)const{assert(reachable(t));std::vector<int>result;for(intv=t;v!=-1;v=parent[v])result.push_back(v);std::reverse(result.begin(),result.end());returnresult;}};namespaceinternal{template<classT>classDijkstraHeap{private:conststd::vector<T>&dist_;std::vector<int>heap_;std::vector<int>position_;boolless(intfirst,intsecond)const{returndist_[heap_[first]]<dist_[heap_[second]];}voidswap_nodes(intfirst,intsecond){std::swap(heap_[first],heap_[second]);position_[heap_[first]]=first;position_[heap_[second]]=second;}voidsift_up(intindex){while(index!=0){constintparent=(index-1)/2;if(!less(index,parent))break;swap_nodes(index,parent);index=parent;}}voidsift_down(intindex){while(2*index+1<int(heap_.size())){intchild=2*index+1;if(child+1<int(heap_.size())&&less(child+1,child)){++child;}if(!less(child,index))break;swap_nodes(index,child);index=child;}}public:DijkstraHeap(conststd::vector<T>&dist,intsize):dist_(dist),position_(size,-1){heap_.reserve(size);}boolempty()const{returnheap_.empty();}voidpush_or_decrease(intvertex){int&position=position_[vertex];if(position==-1){position=int(heap_.size());heap_.push_back(vertex);}sift_up(position);}intpop_min(){constintresult=heap_.front();position_[result]=-1;if(heap_.size()==1){heap_.pop_back();returnresult;}heap_.front()=heap_.back();position_[heap_.front()]=0;heap_.pop_back();sift_down(0);returnresult;}};}// namespace internaltemplate<classT>DijkstraResult<T>dijkstra(constGraph<T>&g,conststd::vector<int>&sources){intn=g.size();DijkstraResult<T>result;result.dist.resize(n);result.reached.assign(n,false);result.parent.assign(n,-1);result.parent_edge.assign(n,-1);internal::DijkstraHeap<T>que(result.dist,n);for(ints:sources){assert(0<=s&&s<n);if(result.reached[s])continue;result.reached[s]=true;result.dist[s]=T();que.push_or_decrease(s);}while(!que.empty()){constintcurrent=que.pop_min();for(constauto&e:g[current]){if(!e.alive)continue;Tnd=result.dist[current]+e.cost;if(result.reached[e.to]&&!(nd<result.dist[e.to]))continue;result.reached[e.to]=true;result.dist[e.to]=std::move(nd);result.parent[e.to]=current;result.parent_edge[e.to]=e.id;que.push_or_decrease(e.to);}}returnresult;}template<classT>DijkstraResult<T>dijkstra(constGraph<T>&g,ints){returndijkstra(g,std::vector<int>{s});}// Compatibility overload: unreachable distances are replaced by inf after the// search. Reachability itself never depends on this sentinel.template<classT>DijkstraResult<T>dijkstra(constGraph<T>&g,conststd::vector<int>&sources,constT&inf){DijkstraResult<T>result=dijkstra(g,sources);result.inf=inf;for(intv=0;v<int(result.dist.size());v++){if(!result.reachable(v))result.dist[v]=inf;}returnresult;}template<classT>DijkstraResult<T>dijkstra(constGraph<T>&g,ints,constT&inf){returndijkstra(g,std::vector<int>{s},inf);}}// namespace graph}// namespace m1une#line 1 "graph/k_shortest_walk.hpp"
#line 10 "graph/k_shortest_walk.hpp"
#line 12 "graph/k_shortest_walk.hpp"
namespacem1une{namespacegraph{namespaceinternal{template<classT>classKShortestWalkHeap{structNode{Tkey;intto;intleft;intright;intrank;};std::vector<Node>_nodes;intrank(introot)const{returnroot==-1?0:_nodes[root].rank;}public:intmake_node(Tkey,intto){intresult=int(_nodes.size());_nodes.push_back(Node{key,to,-1,-1,1});returnresult;}intmeld_mutable(intfirst,intsecond){if(first==-1)returnsecond;if(second==-1)returnfirst;if(_nodes[second].key<_nodes[first].key)std::swap(first,second);_nodes[first].right=meld_mutable(_nodes[first].right,second);if(rank(_nodes[first].left)<rank(_nodes[first].right)){std::swap(_nodes[first].left,_nodes[first].right);}_nodes[first].rank=rank(_nodes[first].right)+1;returnfirst;}intmeld_persistent(intfirst,intsecond){if(first==-1)returnsecond;if(second==-1)returnfirst;if(_nodes[second].key<_nodes[first].key)std::swap(first,second);intresult=int(_nodes.size());_nodes.push_back(_nodes[first]);_nodes[result].right=meld_persistent(_nodes[result].right,second);if(rank(_nodes[result].left)<rank(_nodes[result].right)){std::swap(_nodes[result].left,_nodes[result].right);}_nodes[result].rank=rank(_nodes[result].right)+1;returnresult;}constNode&operator[](intindex)const{return_nodes[index];}};}// namespace internaltemplate<classT>std::vector<T>k_shortest_walk(constGraph<T>&g,ints,intt,intk,Tinf=std::numeric_limits<T>::max()/T(4)){intn=g.size();assert(0<=s&&s<n);assert(0<=t&&t<n);assert(0<=k);if(k==0)return{};structReverseEdge{intfrom;intindex;Tcost;};std::vector<std::vector<ReverseEdge>>reverse_graph(n);for(intfrom=0;from<n;from++){for(intindex=0;index<int(g[from].size());index++){constauto&edge=g[from][index];if(!edge.alive)continue;assert(T(0)<=edge.cost);reverse_graph[edge.to].push_back(ReverseEdge{from,index,edge.cost});}}std::vector<T>dist(n,inf);std::vector<int>tree_edge(n,-1);std::vector<int>order;order.reserve(n);usingQueueEntry=std::pair<T,int>;std::priority_queue<QueueEntry,std::vector<QueueEntry>,std::greater<QueueEntry>>queue;dist[t]=T(0);queue.emplace(T(0),t);while(!queue.empty()){auto[current_dist,vertex]=queue.top();queue.pop();if(dist[vertex]!=current_dist)continue;order.push_back(vertex);for(constauto&edge:reverse_graph[vertex]){Tnext_dist=current_dist+edge.cost;if(dist[edge.from]<=next_dist)continue;dist[edge.from]=next_dist;tree_edge[edge.from]=edge.index;queue.emplace(next_dist,edge.from);}}if(dist[s]==inf)return{};internal::KShortestWalkHeap<T>heap_pool;std::vector<int>local_heap(n,-1);for(intvertex:order){for(intindex=0;index<int(g[vertex].size());index++){constauto&edge=g[vertex][index];if(!edge.alive||dist[edge.to]==inf||index==tree_edge[vertex])continue;Textra=edge.cost+dist[edge.to]-dist[vertex];assert(T(0)<=extra);intnode=heap_pool.make_node(extra,edge.to);local_heap[vertex]=heap_pool.meld_mutable(local_heap[vertex],node);}}std::vector<int>path_heap(n,-1);for(intvertex:order){intinherited=-1;if(tree_edge[vertex]!=-1)inherited=path_heap[g[vertex][tree_edge[vertex]].to];path_heap[vertex]=heap_pool.meld_persistent(inherited,local_heap[vertex]);}std::vector<T>result;result.reserve(k);result.push_back(dist[s]);std::priority_queue<QueueEntry,std::vector<QueueEntry>,std::greater<QueueEntry>>candidates;if(path_heap[s]!=-1){candidates.emplace(dist[s]+heap_pool[path_heap[s]].key,path_heap[s]);}while(int(result.size())<k&&!candidates.empty()){auto[cost,node_index]=candidates.top();candidates.pop();result.push_back(cost);constauto&node=heap_pool[node_index];if(node.left!=-1){candidates.emplace(cost-node.key+heap_pool[node.left].key,node.left);}if(node.right!=-1){candidates.emplace(cost-node.key+heap_pool[node.right].key,node.right);}intnext_heap=path_heap[node.to];if(next_heap!=-1){candidates.emplace(cost+heap_pool[next_heap].key,next_heap);}}returnresult;}}// namespace graph}// namespace m1une#line 1 "graph/warshall_floyd.hpp"
#line 8 "graph/warshall_floyd.hpp"
#line 10 "graph/warshall_floyd.hpp"
namespacem1une{namespacegraph{template<classT>std::vector<std::vector<T>>warshall_floyd(std::vector<std::vector<T>>dist,Tinf=std::numeric_limits<T>::max()/T(4)){intn=int(dist.size());for(intk=0;k<n;k++){for(inti=0;i<n;i++){if(dist[i][k]==inf)continue;for(intj=0;j<n;j++){if(dist[k][j]==inf)continue;Tnd=dist[i][k]+dist[k][j];if(nd<dist[i][j])dist[i][j]=nd;}}}returndist;}template<classT>std::vector<std::vector<T>>warshall_floyd(constGraph<T>&g,Tinf=std::numeric_limits<T>::max()/T(4)){intn=g.size();std::vector<std::vector<T>>dist(n,std::vector<T>(n,inf));for(inti=0;i<n;i++)dist[i][i]=T(0);for(intv=0;v<n;v++){for(constauto&e:g[v]){if(!e.alive)continue;if(e.cost<dist[e.from][e.to])dist[e.from][e.to]=e.cost;}}returnwarshall_floyd(std::move(dist),inf);}template<classT>boolwarshall_floyd_add_directed_edge(std::vector<std::vector<T>>&dist,intfrom,intto,Tcost,Tinf=std::numeric_limits<T>::max()/T(4)){intn=int(dist.size());assert(0<=from&&from<n);assert(0<=to&&to<n);std::vector<T>to_from(n),from_to(n);for(inti=0;i<n;i++){to_from[i]=dist[i][from];from_to[i]=dist[to][i];}boolupdated=false;for(inti=0;i<n;i++){if(to_from[i]==inf)continue;for(intj=0;j<n;j++){if(from_to[j]==inf)continue;Tnd=to_from[i]+cost+from_to[j];if(nd<dist[i][j]){dist[i][j]=nd;updated=true;}}}returnupdated;}template<classT>boolwarshall_floyd_add_undirected_edge(std::vector<std::vector<T>>&dist,intu,intv,Tcost,Tinf=std::numeric_limits<T>::max()/T(4)){intn=int(dist.size());assert(0<=u&&u<n);assert(0<=v&&v<n);std::vector<T>to_u(n),from_u(n),to_v(n),from_v(n);for(inti=0;i<n;i++){to_u[i]=dist[i][u];from_u[i]=dist[u][i];to_v[i]=dist[i][v];from_v[i]=dist[v][i];}boolupdated=false;for(inti=0;i<n;i++){for(intj=0;j<n;j++){if(to_u[i]!=inf&&from_v[j]!=inf){Tnd=to_u[i]+cost+from_v[j];if(nd<dist[i][j]){dist[i][j]=nd;updated=true;}}if(to_v[i]!=inf&&from_u[j]!=inf){Tnd=to_v[i]+cost+from_u[j];if(nd<dist[i][j]){dist[i][j]=nd;updated=true;}}}}returnupdated;}template<classT>boolhas_negative_cycle(conststd::vector<std::vector<T>>&dist){intn=int(dist.size());for(inti=0;i<n;i++){if(dist[i][i]<T(0))returntrue;}returnfalse;}}// namespace graph}// namespace m1une#line 1 "graph/zero_one_bfs.hpp"
#line 6 "graph/zero_one_bfs.hpp"
#include<deque>
#line 9 "graph/zero_one_bfs.hpp"
#line 11 "graph/zero_one_bfs.hpp"
namespacem1une{namespacegraph{structZeroOneBfsResult{std::vector<int>dist;std::vector<int>parent;std::vector<int>parent_edge;intinf;boolreachable(intv)const{assert(0<=v&&v<int(dist.size()));returndist[v]!=inf;}std::vector<int>path(intt)const{assert(reachable(t));std::vector<int>result;for(intv=t;v!=-1;v=parent[v])result.push_back(v);std::reverse(result.begin(),result.end());returnresult;}};template<classT>ZeroOneBfsResultzero_one_bfs(constGraph<T>&g,conststd::vector<int>&sources,intinf=std::numeric_limits<int>::max()/2){intn=g.size();ZeroOneBfsResultresult;result.dist.assign(n,inf);result.parent.assign(n,-1);result.parent_edge.assign(n,-1);result.inf=inf;std::deque<int>deq;for(ints:sources){assert(0<=s&&s<n);if(result.dist[s]==0)continue;result.dist[s]=0;deq.push_back(s);}while(!deq.empty()){intv=deq.front();deq.pop_front();for(constauto&e:g[v]){if(!e.alive)continue;intw;if(e.cost==T(0)){w=0;}else{assert(e.cost==T(1));w=1;}intnd=result.dist[v]+w;if(result.dist[e.to]<=nd)continue;result.dist[e.to]=nd;result.parent[e.to]=v;result.parent_edge[e.to]=e.id;if(w==0){deq.push_front(e.to);}else{deq.push_back(e.to);}}}returnresult;}template<classT>ZeroOneBfsResultzero_one_bfs(constGraph<T>&g,ints,intinf=std::numeric_limits<int>::max()/2){returnzero_one_bfs(g,std::vector<int>{s},inf);}}// namespace graph}// namespace m1une#line 12 "graph/shortest_path.hpp"
#line 1 "graph/two_sat.hpp"
#line 9 "graph/two_sat.hpp"
namespacem1une{namespacegraph{// A 2-SAT solver using iterative strongly connected components.structTwoSat{private:structCsr{std::vector<int>start;std::vector<int>to;};int_n;std::vector<std::pair<int,int>>_edges;bool_solved;bool_satisfiable;std::vector<bool>_answer;intnode(intvariable,boolvalue)const{assert(0<=variable&&variable<_n);return2*variable+int(value);}voidadd_edge(intfrom,intto){_edges.emplace_back(from,to);_solved=false;_answer.clear();}Csrbuild_csr(boolreverse)const{intvertices=2*_n;Csrgraph;graph.start.assign(vertices+1,0);graph.to.resize(_edges.size());for(auto[from,to]:_edges){intsource=reverse?to:from;graph.start[source+1]++;}for(intv=0;v<vertices;v++){graph.start[v+1]+=graph.start[v];}std::vector<int>cursor=graph.start;for(auto[from,to]:_edges){intsource=reverse?to:from;inttarget=reverse?from:to;graph.to[cursor[source]++]=target;}returngraph;}public:TwoSat():TwoSat(0){}explicitTwoSat(intn):_n(n),_solved(false),_satisfiable(false){assert(0<=n);assert(n<=std::numeric_limits<int>::max()/2);}intsize()const{return_n;}boolempty()const{return_n==0;}// Reserves space for approximately `clause_count` two-literal clauses.voidreserve(std::size_tclause_count){assert(clause_count<=std::size_t(std::numeric_limits<int>::max())/2);_edges.reserve(2*clause_count);}// Adds (variable i == f) OR (variable j == g).voidadd_clause(inti,boolf,intj,boolg){inta=node(i,f);intb=node(j,g);add_edge(a^1,b);add_edge(b^1,a);}// Adds (variable i == f) => (variable j == g).voidadd_implication(inti,boolf,intj,boolg){add_clause(i,!f,j,g);}// Forces variable i to equal value.voidset_value(inti,boolvalue){add_clause(i,value,i,value);}// Forces variables i and j to have equal values.voidadd_equal(inti,intj){add_clause(i,false,j,true);add_clause(i,true,j,false);}// Forces variables i and j to have different values.voidadd_not_equal(inti,intj){add_clause(i,true,j,true);add_clause(i,false,j,false);}boolsatisfiable(){if(_solved)return_satisfiable;assert(_edges.size()<=std::size_t(std::numeric_limits<int>::max()));intvertices=2*_n;Csrgraph=build_csr(false);Csrreverse_graph=build_csr(true);std::vector<char>seen(vertices,false);std::vector<int>order;order.reserve(vertices);std::vector<std::pair<int,int>>stack;stack.reserve(vertices);for(intstart=0;start<vertices;start++){if(seen[start])continue;seen[start]=true;stack.emplace_back(start,graph.start[start]);while(!stack.empty()){intv=stack.back().first;int&edge=stack.back().second;if(edge==graph.start[v+1]){order.push_back(v);stack.pop_back();continue;}intto=graph.to[edge++];if(!seen[to]){seen[to]=true;stack.emplace_back(to,graph.start[to]);}}}std::vector<int>component(vertices,-1);std::vector<int>vertices_stack;vertices_stack.reserve(vertices);intcomponent_count=0;for(intindex=vertices-1;index>=0;index--){intstart=order[index];if(component[start]!=-1)continue;component[start]=component_count;vertices_stack.push_back(start);while(!vertices_stack.empty()){intv=vertices_stack.back();vertices_stack.pop_back();for(intedge=reverse_graph.start[v];edge<reverse_graph.start[v+1];edge++){intto=reverse_graph.to[edge];if(component[to]==-1){component[to]=component_count;vertices_stack.push_back(to);}}}component_count++;}_answer.assign(_n,false);_satisfiable=true;for(inti=0;i<_n;i++){if(component[2*i]==component[2*i+1]){_satisfiable=false;_answer.clear();break;}_answer[i]=component[2*i]<component[2*i+1];}_solved=true;return_satisfiable;}conststd::vector<bool>&answer()const{assert(_solved&&_satisfiable);return_answer;}boolvalue(intvariable)const{assert(_solved&&_satisfiable);assert(0<=variable&&variable<_n);return_answer[variable];}};}// namespace graph}// namespace m1une#line 16 "graph/directed.hpp"
#line 1 "graph/dominator_tree.hpp"
#line 7 "graph/dominator_tree.hpp"
#line 9 "graph/dominator_tree.hpp"
namespacem1une{namespacegraph{structDominatorTree{introot;std::vector<int>immediate_dominator;std::vector<std::vector<int>>children;std::vector<int>dfs_order;std::vector<int>tin;std::vector<int>tout;intsize()const{returnint(immediate_dominator.size());}boolreachable(intvertex)const{assert(0<=vertex&&vertex<size());returnimmediate_dominator[vertex]!=-1;}booldominates(intancestor,intvertex)const{assert(0<=ancestor&&ancestor<size());assert(0<=vertex&&vertex<size());returnreachable(ancestor)&&reachable(vertex)&&tin[ancestor]<=tin[vertex]&&tin[vertex]<tout[ancestor];}};// Lengauer-Tarjan immediate dominators from one start vertex.template<classT>DominatorTreedominator_tree(constGraph<T>&graph,introot){intn=graph.size();assert(0<=root&&root<n);std::vector<int>dfs_index(n,-1);std::vector<int>vertex;std::vector<int>parent_vertex(n,-1);std::vector<std::pair<int,int>>stack;dfs_index[root]=0;vertex.push_back(root);stack.emplace_back(root,0);while(!stack.empty()){intcurrent=stack.back().first;int&edge_index=stack.back().second;if(edge_index==int(graph[current].size())){stack.pop_back();continue;}constauto&edge=graph[current][edge_index++];if(!edge.alive||dfs_index[edge.to]!=-1)continue;parent_vertex[edge.to]=current;dfs_index[edge.to]=int(vertex.size());vertex.push_back(edge.to);stack.emplace_back(edge.to,0);}intreachable_count=int(vertex.size());std::vector<std::vector<int>>predecessor(reachable_count);for(intfrom:vertex){for(constauto&edge:graph[from]){if(!edge.alive||dfs_index[edge.to]==-1)continue;predecessor[dfs_index[edge.to]].push_back(dfs_index[from]);}}std::vector<int>parent(reachable_count,-1);for(intindex=1;index<reachable_count;++index){parent[index]=dfs_index[parent_vertex[vertex[index]]];}std::vector<int>semi(reachable_count);std::vector<int>idom(reachable_count,-1);std::vector<int>ancestor(reachable_count,-1);std::vector<int>label(reachable_count);std::vector<std::vector<int>>bucket(reachable_count);for(intindex=0;index<reachable_count;++index){semi[index]=index;label[index]=index;}autocompress=[&](intstart){std::vector<int>path;intcurrent=start;while(ancestor[current]!=-1&&ancestor[ancestor[current]]!=-1){path.push_back(current);current=ancestor[current];}for(intindex=int(path.size())-1;index>=0;--index){intnode=path[index];intparent_node=ancestor[node];if(semi[label[parent_node]]<semi[label[node]]){label[node]=label[parent_node];}ancestor[node]=ancestor[parent_node];}};autoeval=[&](intnode){if(ancestor[node]==-1)returnlabel[node];compress(node);intparent_node=ancestor[node];if(semi[label[parent_node]]<semi[label[node]]){returnlabel[parent_node];}returnlabel[node];};for(intcurrent=reachable_count-1;current>=1;--current){for(intprevious:predecessor[current]){semi[current]=std::min(semi[current],semi[eval(previous)]);}bucket[semi[current]].push_back(current);ancestor[current]=parent[current];intparent_node=parent[current];for(intnode:bucket[parent_node]){intbest=eval(node);idom[node]=semi[best]<semi[node]?best:parent_node;}bucket[parent_node].clear();}for(intcurrent=1;current<reachable_count;++current){if(idom[current]!=semi[current]){idom[current]=idom[idom[current]];}}idom[0]=0;DominatorTreeresult;result.root=root;result.immediate_dominator.assign(n,-1);result.children.assign(n,{});result.dfs_order=vertex;for(intindex=0;index<reachable_count;++index){intcurrent=vertex[index];intdominator=vertex[idom[index]];result.immediate_dominator[current]=dominator;if(current!=root)result.children[dominator].push_back(current);}result.tin.assign(n,-1);result.tout.assign(n,-1);inttimer=0;std::vector<std::pair<int,int>>tree_stack;tree_stack.emplace_back(root,0);result.tin[root]=timer++;while(!tree_stack.empty()){intcurrent=tree_stack.back().first;int&child_index=tree_stack.back().second;if(child_index==int(result.children[current].size())){result.tout[current]=timer;tree_stack.pop_back();continue;}intchild=result.children[current][child_index++];result.tin[child]=timer++;tree_stack.emplace_back(child,0);}returnresult;}}// namespace graph}// namespace m1une#line 1 "graph/flow/flow.hpp"
#line 1 "graph/flow/bounded_flow.hpp"
#line 7 "graph/flow/bounded_flow.hpp"
#line 1 "graph/flow/max_flow.hpp"
#line 9 "graph/flow/max_flow.hpp"
namespacem1une{namespaceflow{template<classCap>structMaxFlow{structEdge{intfrom;intto;Capcap;Capflow;};private:structInternalEdge{intto;intrev;Capcap;};structPosition{intfrom;intedge;};int_n;std::vector<Position>_pos;std::vector<std::vector<InternalEdge>>_g;Caphighest_label_preflow_push(ints,intt){constintdead=2*_n;constintunreachable=_n+1;std::vector<Cap>excess(_n,Cap(0));std::vector<int>state(8*std::size_t(_n)+2);int*height=state.data();int*height_count=height+_n;int*current=height_count+dead+1;int*queue=current+_n;int*next=queue+_n;int*bucket_head=next+_n;std::vector<char>active(_n,false);inthighest=-1;longlongwork=0;constlonglongarc_count=2LL*static_cast<longlong>(_pos.size());constlonglongwork_limit=std::max(1LL,4*arc_count+_n);autoactivate=[&](intv){if(v==s||v==t||active[v]||excess[v]==Cap(0)||height[v]>=dead){return;}active[v]=true;next[v]=bucket_head[height[v]];bucket_head[height[v]]=v;highest=std::max(highest,height[v]);};autorebuild_buckets=[&](){std::fill(bucket_head,bucket_head+dead+1,-1);std::fill(active.begin(),active.end(),false);highest=-1;for(intv=0;v<_n;v++)activate(v);};autoglobal_relabel=[&](){std::fill(height,height+_n,unreachable);std::fill(height_count,height_count+dead+1,0);std::fill(current,current+_n,0);inthead=0;inttail=0;height[t]=0;height[s]=_n;queue[tail++]=t;while(head!=tail){intv=queue[head++];for(constauto&e:_g[v]){if(e.to==s||height[e.to]!=unreachable)continue;constauto&reverse=_g[e.to][e.rev];if(reverse.cap==Cap(0))continue;height[e.to]=height[v]+1;queue[tail++]=e.to;}}for(intv=0;v<_n;v++)height_count[height[v]]++;rebuild_buckets();work=0;};autogap=[&](intempty_height){for(intv=0;v<_n;v++){if(v==s||v==t||height[v]<=empty_height||height[v]>=_n){continue;}height_count[height[v]]--;height[v]=unreachable;height_count[height[v]]++;current[v]=0;}rebuild_buckets();};autorelabel=[&](intv)->bool{intold_height=height[v];intnew_height=dead;work+=int(_g[v].size());for(constauto&e:_g[v]){if(e.cap!=Cap(0)){new_height=std::min(new_height,height[e.to]+1);}}height_count[old_height]--;height[v]=std::min(new_height,dead);height_count[height[v]]++;current[v]=0;if(old_height<_n&&height_count[old_height]==0){gap(old_height);returntrue;}returnfalse;};autopush=[&](intv,InternalEdge&e){Capsent=std::min(excess[v],e.cap);boolwas_zero=excess[e.to]==Cap(0);e.cap-=sent;_g[e.to][e.rev].cap+=sent;excess[v]-=sent;excess[e.to]+=sent;if(was_zero)activate(e.to);};autodischarge=[&](intv){while(excess[v]!=Cap(0)&&height[v]<dead){if(current[v]==int(_g[v].size())){if(relabel(v))return;continue;}auto&e=_g[v][current[v]];work++;if(e.cap!=Cap(0)&&height[v]==height[e.to]+1){push(v,e);}else{current[v]++;}}activate(v);};for(auto&e:_g[s]){if(e.to==s||e.cap==Cap(0))continue;Capsent=e.cap;e.cap=Cap(0);_g[e.to][e.rev].cap+=sent;excess[e.to]+=sent;}global_relabel();while(highest>=0){if(bucket_head[highest]==-1){highest--;continue;}intv=bucket_head[highest];bucket_head[highest]=next[v];if(!active[v]||height[v]!=highest)continue;active[v]=false;discharge(v);if(work>=work_limit)global_relabel();}returnexcess[t];}public:MaxFlow():MaxFlow(0){}explicitMaxFlow(intn):_n(n),_g(n){assert(0<=n);}intsize()const{return_n;}intedge_count()const{returnint(_pos.size());}voidreserve_edges(intedge_count){assert(0<=edge_count);_pos.reserve(edge_count);if(_n==0||edge_count==0||2*std::size_t(edge_count)<std::size_t(_n)){return;}conststd::size_taverage_degree=(3*std::size_t(edge_count)+std::size_t(_n)-1)/std::size_t(_n);for(auto&edges:_g)edges.reserve(average_degree);}voidreserve_edges(intedge_count,conststd::vector<int>°rees){assert(0<=edge_count);assert(int(degrees.size())==_n);_pos.reserve(edge_count);for(intv=0;v<_n;v++){assert(0<=degrees[v]);_g[v].reserve(degrees[v]);}}intadd_edge(intfrom,intto,Capcap){assert(0<=from&&from<_n);assert(0<=to&&to<_n);assert(Cap(0)<=cap);intid=int(_pos.size());intfrom_id=int(_g[from].size());intto_id=int(_g[to].size());if(from==to)to_id++;_pos.push_back(Position{from,from_id});_g[from].push_back(InternalEdge{to,to_id,cap});_g[to].push_back(InternalEdge{from,from_id,Cap(0)});returnid;}intadd_undirected_edge(intfirst,intsecond,Capcap){static_assert(std::numeric_limits<Cap>::is_signed);assert(0<=first&&first<_n);assert(0<=second&&second<_n);assert(Cap(0)<=cap);assert(cap<=std::numeric_limits<Cap>::max()/Cap(2));intid=int(_pos.size());intfirst_id=int(_g[first].size());intsecond_id=int(_g[second].size());if(first==second)second_id++;_pos.push_back(Position{first,~first_id});_g[first].push_back(InternalEdge{second,second_id,cap});_g[second].push_back(InternalEdge{first,first_id,cap});returnid;}Edgeget_edge(inti)const{assert(0<=i&&i<int(_pos.size()));constauto&position=_pos[i];intfrom=position.from;boolundirected=position.edge<0;intidx=undirected?~position.edge:position.edge;constauto&e=_g[from][idx];constauto&re=_g[e.to][e.rev];if(undirected){returnEdge{from,e.to,(e.cap+re.cap)/Cap(2),(re.cap-e.cap)/Cap(2)};}returnEdge{from,e.to,e.cap+re.cap,re.cap};}std::vector<Edge>edges()const{std::vector<Edge>result;result.reserve(_pos.size());for(inti=0;i<int(_pos.size());i++)result.push_back(get_edge(i));returnresult;}voidchange_edge(inti,Capnew_cap,Capnew_flow){assert(0<=i&&i<int(_pos.size()));assert(Cap(0)<=new_cap);auto&position=_pos[i];intfrom=position.from;boolundirected=position.edge<0;intidx=undirected?~position.edge:position.edge;auto&e=_g[from][idx];auto&re=_g[e.to][e.rev];if(undirected){assert(new_cap<=std::numeric_limits<Cap>::max()/Cap(2));assert(-new_cap<=new_flow&&new_flow<=new_cap);e.cap=new_cap-new_flow;re.cap=new_cap+new_flow;}else{assert(Cap(0)<=new_flow&&new_flow<=new_cap);e.cap=new_cap-new_flow;re.cap=new_flow;}}Capmax_flow(ints,intt){assert(0<=s&&s<_n);assert(0<=t&&t<_n);assert(s!=t);returnhighest_label_preflow_push(s,t);}Capmax_flow_push_relabel(ints,intt){assert(0<=s&&s<_n);assert(0<=t&&t<_n);assert(s!=t);returnhighest_label_preflow_push(s,t);}Capmax_flow_dinic(ints,intt){returnmax_flow(s,t,std::numeric_limits<Cap>::max());}Capmax_flow(ints,intt,Capflow_limit){assert(0<=s&&s<_n);assert(0<=t&&t<_n);assert(s!=t);std::vector<int>work(3*std::size_t(_n));int*level=work.data();int*iter=level+_n;int*queue=iter+_n;autobfs=[&]()->bool{std::fill(level,level+_n,-1);inthead=0;inttail=0;level[s]=0;queue[tail++]=s;while(head!=tail){intv=queue[head++];for(constauto&e:_g[v]){if(level[e.to]!=-1||e.cap==Cap(0))continue;level[e.to]=level[v]+1;if(e.to==t)returntrue;queue[tail++]=e.to;}}returnlevel[t]!=-1;};autodfs=[&](auto&&self,intv,Capup)->Cap{if(v==s)returnup;Capresult=Cap(0);constintcurrent_level=level[v];auto&edges=_g[v];constintedge_count=int(edges.size());for(int&i=iter[v];i<edge_count;i++){auto&e=edges[i];if(level[e.to]+1!=current_level)continue;auto&reverse=_g[e.to][e.rev];if(reverse.cap==Cap(0))continue;Capd=self(self,e.to,std::min(up-result,reverse.cap));if(d==Cap(0))continue;e.cap+=d;reverse.cap-=d;result+=d;if(result==up)returnresult;}level[v]=_n;returnresult;};Capflow=0;while(flow<flow_limit&&bfs()){std::fill(iter,iter+_n,0);flow+=dfs(dfs,t,flow_limit-flow);}returnflow;}std::vector<bool>min_cut(ints)const{assert(0<=s&&s<_n);std::vector<bool>visited(_n,false);std::vector<int>queue(_n);inthead=0;inttail=0;visited[s]=true;queue[tail++]=s;while(head!=tail){intv=queue[head++];for(constauto&e:_g[v]){if(e.cap==Cap(0)||visited[e.to])continue;visited[e.to]=true;queue[tail++]=e.to;}}returnvisited;}};}// namespace flow}// namespace m1une#line 9 "graph/flow/bounded_flow.hpp"
namespacem1une{namespaceflow{template<classCap>structBoundedFlow{structEdge{intfrom;intto;Caplower;Capupper;};structResultEdge{intfrom;intto;Caplower;Capupper;Capflow;};structResult{std::vector<ResultEdge>edges;std::vector<Cap>balance;ResultEdgeget_edge(inti)const{assert(0<=i&&i<int(edges.size()));returnedges[i];}Capflow(inti)const{assert(0<=i&&i<int(edges.size()));returnedges[i].flow;}};private:int_n;std::vector<Edge>_edges;std::vector<Cap>_balance;public:BoundedFlow():BoundedFlow(0){}explicitBoundedFlow(intn):_n(n),_balance(n,Cap(0)){assert(0<=n);}intsize()const{return_n;}intedge_count()const{returnint(_edges.size());}intadd_edge(intfrom,intto,Caplower,Capupper){assert(0<=from&&from<_n);assert(0<=to&&to<_n);assert(lower<=upper);intid=int(_edges.size());_edges.push_back(Edge{from,to,lower,upper});returnid;}Edgeget_edge(inti)const{assert(0<=i&&i<int(_edges.size()));return_edges[i];}std::vector<Edge>edges()const{return_edges;}voidset_balance(intv,Capb){assert(0<=v&&v<_n);_balance[v]=b;}voidadd_balance(intv,Capb){assert(0<=v&&v<_n);_balance[v]+=b;}voidadd_supply(intv,Capsupply){assert(Cap(0)<=supply);add_balance(v,supply);}voidadd_demand(intv,Capdemand){assert(Cap(0)<=demand);add_balance(v,-demand);}Capbalance(intv)const{assert(0<=v&&v<_n);return_balance[v];}conststd::vector<Cap>&balances()const{return_balance;}std::optional<Result>feasible_flow()const{returnfeasible_flow(_balance);}std::optional<Result>feasible_flow(conststd::vector<Cap>&balance)const{assert(int(balance.size())==_n);intss=_n,tt=_n+1;MaxFlow<Cap>mf(_n+2);std::vector<int>edge_ids;edge_ids.reserve(_edges.size());std::vector<Cap>need=balance;for(constauto&e:_edges){edge_ids.push_back(mf.add_edge(e.from,e.to,e.upper-e.lower));need[e.from]-=e.lower;need[e.to]+=e.lower;}Cappositive_sum=Cap(0),negative_sum=Cap(0);for(intv=0;v<_n;v++){if(need[v]>Cap(0)){positive_sum+=need[v];mf.add_edge(ss,v,need[v]);}elseif(need[v]<Cap(0)){negative_sum+=-need[v];mf.add_edge(v,tt,-need[v]);}}if(positive_sum!=negative_sum)returnstd::nullopt;if(mf.max_flow(ss,tt)!=positive_sum)returnstd::nullopt;Resultresult;result.balance=balance;result.edges.reserve(_edges.size());for(inti=0;i<int(_edges.size());i++){autoused=mf.get_edge(edge_ids[i]).flow;constauto&e=_edges[i];result.edges.push_back(ResultEdge{e.from,e.to,e.lower,e.upper,e.lower+used});}returnresult;}std::optional<Result>feasible_st_flow(ints,intt,Capflow_value)const{assert(0<=s&&s<_n);assert(0<=t&&t<_n);assert(s!=t);std::vector<Cap>balance=_balance;balance[s]+=flow_value;balance[t]-=flow_value;returnfeasible_flow(balance);}};template<classCap>usingBFlow=BoundedFlow<Cap>;}// namespace flow}// namespace m1une#line 1 "graph/flow/bounded_min_cost_flow.hpp"
#line 7 "graph/flow/bounded_min_cost_flow.hpp"
#include<cmath>
#line 14 "graph/flow/bounded_min_cost_flow.hpp"
namespacem1une{namespaceflow{template<classCap,classCost,classTotalCost=Cost,std::size_tPivotLimitFactor=8>structBoundedMinCostFlow{static_assert(std::numeric_limits<Cap>::is_integer);static_assert(std::numeric_limits<Cap>::is_signed);static_assert(std::numeric_limits<Cost>::is_specialized);static_assert(std::numeric_limits<Cost>::is_signed);structEdge{intfrom;intto;Caplower;Capupper;Costcost;};structResultEdge{intfrom;intto;Caplower;Capupper;Capflow;Costcost;};structResult{std::vector<ResultEdge>edges;std::vector<Cap>balance;std::vector<Cost>potential;TotalCostcost;ResultEdgeget_edge(inti)const{assert(0<=i&&i<int(edges.size()));returnedges[i];}Capflow(inti)const{assert(0<=i&&i<int(edges.size()));returnedges[i].flow;}};private:structNetworkEdge{intto;Capcap;Costcost;};structNetworkSimplexSolver{enumclassStatus{optimal,infeasible,pivot_limit_reached,};structParent{intvertex;intedge;Capup;Capdown;};intn;std::vector<NetworkEdge>edges;std::vector<Cap>excess;std::vector<Cost>potential;std::size_tpivot_count=0;NetworkSimplexSolver(intvertex_count,conststd::vector<Cap>&balance):n(vertex_count),excess(balance){}voidreserve_edges(intedge_count){edges.reserve(2*(edge_count+n));}intadd_edge(intfrom,intto,Caplower,Capupper,Costcost){intid=int(edges.size())/2;edges.push_back(NetworkEdge{to,upper-lower,cost});edges.push_back(NetworkEdge{from,Cap(0),-cost});excess[from]-=lower;excess[to]+=lower;returnid;}Statussolve(std::size_tpivot_limit){pivot_count=0;constintoriginal_edge_count=int(edges.size());potential.assign(n+1,Cost(0));Costartificial_cost=Cost(1);for(intedge=0;edge<original_edge_count;edge+=2){artificial_cost+=edges[edge].cost<Cost(0)?-edges[edge].cost:edges[edge].cost;}std::vector<Parent>parent(n);edges.reserve(original_edge_count+2*n);for(intvertex=0;vertex<n;vertex++){if(excess[vertex]>=Cap(0)){edges.push_back(NetworkEdge{n,Cap(0),artificial_cost});edges.push_back(NetworkEdge{vertex,excess[vertex],-artificial_cost});potential[vertex]=-artificial_cost;}else{edges.push_back(NetworkEdge{n,-excess[vertex],-artificial_cost});edges.push_back(NetworkEdge{vertex,Cap(0),artificial_cost});potential[vertex]=artificial_cost;}intedge=int(edges.size())-2;parent[vertex]=Parent{n,edge,edges[edge].cap,edges[edge^1].cap};}std::vector<int>depth(n+1,1);depth[n]=0;std::vector<int>next(2*(n+1));std::vector<int>previous(2*(n+1));autoconnect=[&](intfirst,intsecond){next[first]=second;previous[second]=first;};for(intvertex=0;vertex<=n;vertex++){connect(2*vertex,2*vertex+1);}for(intvertex=0;vertex<n;vertex++){connect(2*vertex+1,next[2*n]);connect(2*n,2*vertex);}autopush_flow=[&](intentering_edge){constintfirst=edges[entering_edge^1].to;constintsecond=edges[entering_edge].to;constCostcycle_cost=edges[entering_edge].cost+potential[first]-potential[second];Capamount=edges[entering_edge].cap;boolleave_first_side=true;intleaving_vertex=second;intfirst_ancestor=first;intsecond_ancestor=second;automove_first_up=[&]{if(parent[first_ancestor].down<amount){amount=parent[first_ancestor].down;leaving_vertex=first_ancestor;leave_first_side=true;}first_ancestor=parent[first_ancestor].vertex;};automove_second_up=[&]{if(parent[second_ancestor].up<=amount){amount=parent[second_ancestor].up;leaving_vertex=second_ancestor;leave_first_side=false;}second_ancestor=parent[second_ancestor].vertex;};if(depth[first_ancestor]>=depth[second_ancestor]){intdifference=depth[first_ancestor]-depth[second_ancestor];for(inti=0;i<difference;i++)move_first_up();}else{intdifference=depth[second_ancestor]-depth[first_ancestor];for(inti=0;i<difference;i++)move_second_up();}while(first_ancestor!=second_ancestor){move_first_up();move_second_up();}constintancestor=first_ancestor;if(amount!=Cap(0)){intvertex=first;while(vertex!=ancestor){parent[vertex].up+=amount;parent[vertex].down-=amount;vertex=parent[vertex].vertex;}vertex=second;while(vertex!=ancestor){parent[vertex].up-=amount;parent[vertex].down+=amount;vertex=parent[vertex].vertex;}}intvertex=first;intnew_parent=second;std::pair<Cap,Cap>parent_capacities{edges[entering_edge].cap-amount,edges[entering_edge^1].cap+amount};Costpotential_difference=-cycle_cost;if(!leave_first_side){std::swap(vertex,new_parent);std::swap(parent_capacities.first,parent_capacities.second);potential_difference=-potential_difference;}intparent_edge=entering_edge^(leave_first_side?0:1);while(new_parent!=leaving_vertex){intnew_depth=depth[new_parent];inttour_index=2*vertex;while(tour_index!=2*vertex+1){if((tour_index&1)==0){new_depth++;potential[tour_index/2]+=potential_difference;depth[tour_index/2]=new_depth;}else{new_depth--;}tour_index=next[tour_index];}connect(previous[2*vertex],next[2*vertex+1]);connect(2*vertex+1,next[2*new_parent]);connect(2*new_parent,2*vertex);std::swap(parent[vertex].edge,parent_edge);parent_edge^=1;std::swap(parent[vertex].up,parent_capacities.first);std::swap(parent[vertex].down,parent_capacities.second);std::swap(parent_capacities.first,parent_capacities.second);intold_parent=parent[vertex].vertex;parent[vertex].vertex=new_parent;new_parent=vertex;vertex=old_parent;}edges[parent_edge].cap=parent_capacities.first;edges[parent_edge^1].cap=parent_capacities.second;};boolpivot_limit_reached=false;autopivot=[&](intentering_edge){if(pivot_count==pivot_limit){pivot_limit_reached=true;returnfalse;}push_flow(entering_edge);pivot_count++;returntrue;};constintcandidate_limit=std::max(int(0.2*std::sqrt(double(original_edge_count))),10);constintminor_limit=std::max(candidate_limit/10,3);std::vector<int>candidates;candidates.reserve(candidate_limit);autominor_pivot=[&]{Costbest_cost=Cost(0);intbest_edge=-1;intindex=0;while(index<int(candidates.size())){intedge=candidates[index];if(edges[edge].cap==Cap(0)){candidates[index]=candidates.back();candidates.pop_back();continue;}Costreduced_cost=edges[edge].cost+potential[edges[edge^1].to]-potential[edges[edge].to];if(reduced_cost>=Cost(0)){candidates[index]=candidates.back();candidates.pop_back();continue;}if(reduced_cost<best_cost){best_cost=reduced_cost;best_edge=edge;}index++;}if(best_edge==-1)returnfalse;returnpivot(best_edge);};intedge=0;while(true){for(intiteration=0;iteration<minor_limit;iteration++){if(!minor_pivot())break;}if(pivot_limit_reached)returnStatus::pivot_limit_reached;Costbest_cost=Cost(0);intbest_edge=-1;candidates.clear();for(intscanned=0;scanned<int(edges.size());scanned++){if(edges[edge].cap!=Cap(0)){Costreduced_cost=edges[edge].cost+potential[edges[edge^1].to]-potential[edges[edge].to];if(reduced_cost<Cost(0)){if(reduced_cost<best_cost){best_cost=reduced_cost;best_edge=edge;}candidates.push_back(edge);if(int(candidates.size())==candidate_limit)break;}}edge++;if(edge==int(edges.size()))edge=0;}if(candidates.empty())break;if(!pivot(best_edge))returnStatus::pivot_limit_reached;}for(intvertex=0;vertex<n;vertex++){edges[parent[vertex].edge].cap=parent[vertex].up;edges[parent[vertex].edge^1].cap=parent[vertex].down;}boolfeasible=true;for(intvertex=0;vertex<n;vertex++){intartificial_edge=original_edge_count+2*vertex;if((excess[vertex]>=Cap(0)&&edges[artificial_edge^1].cap!=Cap(0))||(excess[vertex]<Cap(0)&&edges[artificial_edge].cap!=Cap(0))){feasible=false;break;}}potential.pop_back();returnfeasible?Status::optimal:Status::infeasible;}Capedge_flow(intedge_id,Caplower)const{returnlower+edges[2*edge_id+1].cap;}};structScalingEdge{intto;intreverse;Capcap;Capflow;Costcost;};structScalingSolver{intn;std::vector<std::vector<ScalingEdge>>graph;std::vector<std::pair<int,int>>positions;std::vector<Cap>excess;std::vector<Cost>potential;std::vector<Cost>distance;std::vector<int>parent_vertex;std::vector<int>parent_edge;std::vector<int>excess_vertices;std::vector<int>deficit_vertices;Costfarthest=Cost(0);ScalingSolver(intvertex_count,conststd::vector<Cap>&balance):n(vertex_count),graph(vertex_count),excess(balance),potential(vertex_count,Cost(0)){}voidreserve_edges(intedge_count){positions.reserve(edge_count);}intadd_edge(intfrom,intto,Caplower,Capupper,Costcost){intid=int(positions.size());intfrom_edge=int(graph[from].size());intto_edge=int(graph[to].size());if(from==to)to_edge++;positions.emplace_back(from,from_edge);graph[from].push_back(ScalingEdge{to,to_edge,upper,Cap(0),cost});graph[to].push_back(ScalingEdge{from,from_edge,-lower,Cap(0),-cost});returnid;}Capresidual_capacity(intfrom,intedge_id)const{constauto&edge=graph[from][edge_id];returnedge.cap-edge.flow;}Costresidual_cost(intfrom,constScalingEdge&edge)const{returnedge.cost+potential[from]-potential[edge.to];}voidpush(intfrom,intedge_id,Capamount){auto&edge=graph[from][edge_id];edge.flow+=amount;graph[edge.to][edge.reverse].flow-=amount;}voidsaturate_negative(Capdelta){excess_vertices.clear();deficit_vertices.clear();for(intfrom=0;from<n;from++){for(intedge_id=0;edge_id<int(graph[from].size());edge_id++){constauto&edge=graph[from][edge_id];Capresidual=edge.cap-edge.flow;residual-=residual%delta;if(residual_cost(from,edge)<Cost(0)||residual<Cap(0)){intto=edge.to;push(from,edge_id,residual);excess[from]-=residual;excess[to]+=residual;}}}for(intvertex=0;vertex<n;vertex++){if(excess[vertex]>Cap(0)){excess_vertices.push_back(vertex);}elseif(excess[vertex]<Cap(0)){deficit_vertices.push_back(vertex);}}}booldual(Capdelta){excess_vertices.erase(std::remove_if(excess_vertices.begin(),excess_vertices.end(),[&](intvertex){returnexcess[vertex]<delta;}),excess_vertices.end());deficit_vertices.erase(std::remove_if(deficit_vertices.begin(),deficit_vertices.end(),[&](intvertex){returnexcess[vertex]>-delta;}),deficit_vertices.end());constCostunreachable=std::numeric_limits<Cost>::max();distance.assign(n,unreachable);parent_vertex.assign(n,-1);parent_edge.assign(n,-1);usingQueueEntry=std::pair<Cost,int>;std::priority_queue<QueueEntry,std::vector<QueueEntry>,std::greater<QueueEntry>>queue;for(intvertex:excess_vertices){distance[vertex]=Cost(0);queue.emplace(Cost(0),vertex);}farthest=Cost(0);intreached_deficits=0;while(!queue.empty()){auto[current_distance,from]=queue.top();queue.pop();if(distance[from]!=current_distance)continue;farthest=current_distance;if(excess[from]<=-delta)reached_deficits++;if(reached_deficits>=int(deficit_vertices.size()))break;for(intedge_id=0;edge_id<int(graph[from].size());edge_id++){constauto&edge=graph[from][edge_id];if(edge.cap-edge.flow<delta)continue;Costnext_distance=current_distance+residual_cost(from,edge);if(next_distance>=distance[edge.to])continue;distance[edge.to]=next_distance;parent_vertex[edge.to]=from;parent_edge[edge.to]=edge_id;queue.emplace(next_distance,edge.to);}}for(intvertex=0;vertex<n;vertex++){potential[vertex]+=std::min(distance[vertex],farthest);}returnreached_deficits>0;}voidprimal(Capdelta){for(intsink:deficit_vertices){if(distance[sink]>farthest)continue;Capamount=-excess[sink];introot=sink;while(parent_edge[root]!=-1){intfrom=parent_vertex[root];amount=std::min(amount,residual_capacity(from,parent_edge[root]));root=from;}amount=std::min(amount,excess[root]);amount-=amount%delta;if(amount<=Cap(0))continue;intvertex=sink;while(parent_edge[vertex]!=-1){intfrom=parent_vertex[vertex];intedge_id=parent_edge[vertex];push(from,edge_id,amount);if(residual_capacity(from,edge_id)==Cap(0)){parent_edge[vertex]=-1;}vertex=from;}excess[sink]+=amount;excess[root]-=amount;}}boolsolve(){Capscale_bound=Cap(1);for(Capvalue:excess){scale_bound=std::max(scale_bound,value);scale_bound=std::max(scale_bound,-value);}for(constauto&edges:graph){for(constauto&edge:edges){Capresidual=edge.cap-edge.flow;scale_bound=std::max(scale_bound,residual);scale_bound=std::max(scale_bound,-residual);}}Capdelta=Cap(1);while(delta<=scale_bound/Cap(2))delta*=Cap(2);while(true){saturate_negative(delta);while(dual(delta))primal(delta);if(delta==Cap(1))break;delta/=Cap(2);}returnexcess_vertices.empty()&&deficit_vertices.empty();}Capedge_flow(intedge_id,Cap)const{auto[from,index]=positions[edge_id];returngraph[from][index].flow;}};int_n;std::vector<Edge>_edges;std::vector<Cap>_balance;template<classSolver>Resultmake_result(conststd::vector<Cap>&balance,constSolver&solver,std::vector<Cost>potential)const{Resultresult;result.balance=balance;result.cost=TotalCost(0);result.edges.reserve(_edges.size());for(inti=0;i<int(_edges.size());i++){constauto&edge=_edges[i];Capflow=solver.edge_flow(i,edge.lower);result.cost+=TotalCost(flow)*TotalCost(edge.cost);result.edges.push_back(ResultEdge{edge.from,edge.to,edge.lower,edge.upper,flow,edge.cost});}result.potential=std::move(potential);returnresult;}std::vector<Cost>residual_potential(conststd::vector<ResultEdge>&edges)const{std::vector<Cost>potential(_n,Cost(0));boolupdated=false;for(intiteration=0;iteration<_n;iteration++){updated=false;for(constResultEdge&edge:edges){if(edge.flow<edge.upper&&potential[edge.to]>potential[edge.from]+edge.cost){potential[edge.to]=potential[edge.from]+edge.cost;updated=true;}if(edge.lower<edge.flow&&potential[edge.from]>potential[edge.to]-edge.cost){potential[edge.from]=potential[edge.to]-edge.cost;updated=true;}}if(!updated)break;}assert(!updated);returnpotential;}std::optional<Result>polynomial_min_cost_flow_impl(conststd::vector<Cap>&balance)const{ScalingSolversolver(_n,balance);solver.reserve_edges(int(_edges.size()));for(constauto&edge:_edges){solver.add_edge(edge.from,edge.to,edge.lower,edge.upper,edge.cost);}if(!solver.solve())returnstd::nullopt;Resultresult=make_result(balance,solver,{});result.potential=residual_potential(result.edges);returnresult;}public:BoundedMinCostFlow():BoundedMinCostFlow(0){}explicitBoundedMinCostFlow(intn):_n(n),_balance(n,Cap(0)){assert(0<=n);}intsize()const{return_n;}intedge_count()const{returnint(_edges.size());}voidreserve_edges(intedge_count){assert(0<=edge_count);_edges.reserve(edge_count);}intadd_edge(intfrom,intto,Caplower,Capupper,Costcost){assert(0<=from&&from<_n);assert(0<=to&&to<_n);assert(lower<=upper);intid=int(_edges.size());_edges.push_back(Edge{from,to,lower,upper,cost});returnid;}Edgeget_edge(inti)const{assert(0<=i&&i<int(_edges.size()));return_edges[i];}std::vector<Edge>edges()const{return_edges;}voidset_balance(intv,Capb){assert(0<=v&&v<_n);_balance[v]=b;}voidadd_balance(intv,Capb){assert(0<=v&&v<_n);_balance[v]+=b;}voidadd_supply(intv,Capsupply){assert(Cap(0)<=supply);add_balance(v,supply);}voidadd_demand(intv,Capdemand){assert(Cap(0)<=demand);add_balance(v,-demand);}Capbalance(intv)const{assert(0<=v&&v<_n);return_balance[v];}conststd::vector<Cap>&balances()const{return_balance;}std::optional<Result>min_cost_flow()const{returnmin_cost_flow(_balance);}std::optional<Result>min_cost_flow(conststd::vector<Cap>&balance)const{assert(int(balance.size())==_n);Capbalance_sum=Cap(0);for(Capvalue:balance)balance_sum+=value;if(balance_sum!=Cap(0))returnstd::nullopt;NetworkSimplexSolversolver(_n,balance);solver.reserve_edges(int(_edges.size()));for(constauto&edge:_edges){solver.add_edge(edge.from,edge.to,edge.lower,edge.upper,edge.cost);}conststd::size_tgraph_size=std::size_t(_n)+_edges.size()+1;std::size_tpivot_limit=0;ifconstexpr(PivotLimitFactor!=0){conststd::size_tmaximum=std::numeric_limits<std::size_t>::max();pivot_limit=graph_size>maximum/PivotLimitFactor?maximum:PivotLimitFactor*graph_size;}autostatus=solver.solve(pivot_limit);if(status==NetworkSimplexSolver::Status::infeasible){returnstd::nullopt;}if(status==NetworkSimplexSolver::Status::pivot_limit_reached){returnpolynomial_min_cost_flow_impl(balance);}returnmake_result(balance,solver,std::move(solver.potential));}std::optional<Result>min_cost_flow_polynomial()const{returnmin_cost_flow_polynomial(_balance);}std::optional<Result>min_cost_flow_polynomial(conststd::vector<Cap>&balance)const{assert(int(balance.size())==_n);Capbalance_sum=Cap(0);for(Capvalue:balance)balance_sum+=value;if(balance_sum!=Cap(0))returnstd::nullopt;returnpolynomial_min_cost_flow_impl(balance);}std::optional<Result>min_cost_st_flow(ints,intt,Capflow_value)const{assert(0<=s&&s<_n);assert(0<=t&&t<_n);assert(s!=t);std::vector<Cap>balance=_balance;balance[s]+=flow_value;balance[t]-=flow_value;returnmin_cost_flow(balance);}std::optional<Result>min_cost_st_flow_polynomial(ints,intt,Capflow_value)const{assert(0<=s&&s<_n);assert(0<=t&&t<_n);assert(s!=t);std::vector<Cap>balance=_balance;balance[s]+=flow_value;balance[t]-=flow_value;returnmin_cost_flow_polynomial(balance);}};template<classCap,classCost,classTotalCost=Cost,std::size_tPivotLimitFactor=8>usingBMinCostFlow=BoundedMinCostFlow<Cap,Cost,TotalCost,PivotLimitFactor>;}// namespace flow}// namespace m1une#line 1 "graph/flow/gomory_hu.hpp"
#line 9 "graph/flow/gomory_hu.hpp"
namespacem1une{namespaceflow{template<classCap>structGomoryHu{structEdge{intu;intv;Capcap;};private:structFlowEdge{intto;intrev;Capcap;Capinitial_cap;};int_n;bool_built=false;std::vector<Edge>_edges;std::vector<Edge>_tree_edges;std::vector<int>_parent;std::vector<Cap>_cut_value;std::vector<std::vector<std::pair<int,Cap>>>_tree;std::vector<std::vector<int>>_up;std::vector<std::vector<Cap>>_minimum;std::vector<int>_depth;std::vector<std::vector<FlowEdge>>_graph;std::vector<Cap>_excess;std::vector<int>_height;std::vector<int>_height_count;std::vector<int>_current;std::vector<bool>_active;std::vector<std::vector<int>>_buckets;std::vector<int>_queue;int_highest;longlong_work;longlong_work_limit;voidadd_flow_edge(intu,intv,Capcap){if(u==v||cap==Cap(0))return;intui=int(_graph[u].size());intvi=int(_graph[v].size());_graph[u].push_back(FlowEdge{v,vi,cap,cap});_graph[v].push_back(FlowEdge{u,ui,cap,cap});}voidreset_flow(){for(auto&edges:_graph){for(auto&edge:edges)edge.cap=edge.initial_cap;}}voidactivate(intv,ints,intt){intdead=2*_n;if(v==s||v==t||_active[v]||_excess[v]==Cap(0)||_height[v]>=dead)return;_active[v]=true;_buckets[_height[v]].push_back(v);_highest=std::max(_highest,_height[v]);}voidrebuild_buckets(ints,intt){for(auto&bucket:_buckets)bucket.clear();std::fill(_active.begin(),_active.end(),false);_highest=-1;for(intv=0;v<_n;v++)activate(v,s,t);}voidglobal_relabel(ints,intt){intdead=2*_n;intunreachable=_n+1;std::fill(_height.begin(),_height.end(),unreachable);std::fill(_height_count.begin(),_height_count.end(),0);std::fill(_current.begin(),_current.end(),0);inthead=0;inttail=0;_height[t]=0;_height[s]=_n;_queue[tail++]=t;while(head<tail){intv=_queue[head++];for(constauto&edge:_graph[v]){constFlowEdge&reverse=_graph[edge.to][edge.rev];if(reverse.cap==Cap(0)||_height[edge.to]!=unreachable)continue;_height[edge.to]=_height[v]+1;_queue[tail++]=edge.to;}}for(intv=0;v<_n;v++){_height[v]=std::min(_height[v],dead);_height_count[_height[v]]++;}rebuild_buckets(s,t);_work=0;}voidpush(intv,FlowEdge&edge,ints,intt){if(edge.cap==Cap(0)||_height[v]!=_height[edge.to]+1)return;Capsent=std::min(_excess[v],edge.cap);if(sent==Cap(0))return;boolwas_zero=_excess[edge.to]==Cap(0);edge.cap-=sent;_graph[edge.to][edge.rev].cap+=sent;_excess[v]-=sent;_excess[edge.to]+=sent;if(was_zero)activate(edge.to,s,t);}voidgap(intheight,ints,intt){intunreachable=_n+1;for(intv=0;v<_n;v++){if(v==s||v==t||_height[v]<=height||_height[v]>=_n)continue;_height_count[_height[v]]--;_height[v]=unreachable;_height_count[_height[v]]++;_current[v]=0;}rebuild_buckets(s,t);}boolrelabel(intv,ints,intt){intdead=2*_n;intold_height=_height[v];intnew_height=dead;_work+=int(_graph[v].size());for(constauto&edge:_graph[v]){if(edge.cap!=Cap(0))new_height=std::min(new_height,_height[edge.to]+1);}_height_count[old_height]--;_height[v]=std::min(new_height,dead);_height_count[_height[v]]++;_current[v]=0;if(old_height<_n&&_height_count[old_height]==0){gap(old_height,s,t);returntrue;}returnfalse;}voiddischarge(intv,ints,intt){while(_excess[v]!=Cap(0)&&_height[v]<2*_n){if(_current[v]==int(_graph[v].size())){if(relabel(v,s,t))return;continue;}FlowEdge&edge=_graph[v][_current[v]];_work++;if(edge.cap!=Cap(0)&&_height[v]==_height[edge.to]+1){push(v,edge,s,t);}else{_current[v]++;}}activate(v,s,t);}Capmax_flow(ints,intt){reset_flow();std::fill(_excess.begin(),_excess.end(),Cap(0));for(auto&edge:_graph[s]){Capsent=edge.cap;if(sent==Cap(0))continue;edge.cap=Cap(0);_graph[edge.to][edge.rev].cap+=sent;_excess[edge.to]+=sent;}global_relabel(s,t);while(_highest>=0){if(_buckets[_highest].empty()){_highest--;continue;}intv=_buckets[_highest].back();_buckets[_highest].pop_back();if(!_active[v]||_height[v]!=_highest)continue;_active[v]=false;discharge(v,s,t);if(_work>=_work_limit)global_relabel(s,t);}return_excess[t];}std::vector<bool>source_side(ints){std::vector<bool>visited(_n,false);inthead=0;inttail=0;visited[s]=true;_queue[tail++]=s;while(head<tail){intv=_queue[head++];for(constauto&edge:_graph[v]){if(edge.cap==Cap(0)||visited[edge.to])continue;visited[edge.to]=true;_queue[tail++]=edge.to;}}returnvisited;}voidbuild_query_table(){intlog=1;while((1LL<<log)<=std::max(1,_n))log++;constCapinfinity=std::numeric_limits<Cap>::max();_up.assign(log,std::vector<int>(_n,0));_minimum.assign(log,std::vector<Cap>(_n,infinity));_depth.assign(_n,0);if(_n==0)return;std::vector<int>order;order.reserve(_n);order.push_back(0);for(inti=0;i<int(order.size());i++){intv=order[i];for(auto[to,cap]:_tree[v]){if(to==_up[0][v]&&v!=0)continue;_up[0][to]=v;_minimum[0][to]=cap;_depth[to]=_depth[v]+1;order.push_back(to);}}for(intk=1;k<log;k++){for(intv=0;v<_n;v++){intmiddle=_up[k-1][v];_up[k][v]=_up[k-1][middle];_minimum[k][v]=std::min(_minimum[k-1][v],_minimum[k-1][middle]);}}}public:GomoryHu():GomoryHu(0){}explicitGomoryHu(intn):_n(n){assert(0<=n);}intsize()const{return_n;}intedge_count()const{returnint(_edges.size());}intadd_edge(intu,intv,Capcap){assert(0<=u&&u<_n);assert(0<=v&&v<_n);assert(Cap(0)<=cap);_built=false;intid=int(_edges.size());_edges.push_back(Edge{u,v,cap});returnid;}voidbuild(){std::vector<Edge>flow_edges;flow_edges.reserve(_edges.size());for(autoedge:_edges){if(edge.u==edge.v||edge.cap==Cap(0))continue;if(edge.u>edge.v)std::swap(edge.u,edge.v);flow_edges.push_back(edge);}std::sort(flow_edges.begin(),flow_edges.end(),[](constEdge&lhs,constEdge&rhs){returnstd::pair<int,int>(lhs.u,lhs.v)<std::pair<int,int>(rhs.u,rhs.v);});intunique_edges=0;for(constauto&edge:flow_edges){if(unique_edges>0&&flow_edges[unique_edges-1].u==edge.u&&flow_edges[unique_edges-1].v==edge.v){flow_edges[unique_edges-1].cap+=edge.cap;}else{flow_edges[unique_edges++]=edge;}}flow_edges.resize(unique_edges);_graph.assign(_n,{});std::vector<int>degree(_n,0);for(constauto&edge:flow_edges){degree[edge.u]++;degree[edge.v]++;}for(intv=0;v<_n;v++)_graph[v].reserve(degree[v]);for(constauto&edge:flow_edges)add_flow_edge(edge.u,edge.v,edge.cap);_excess.resize(_n);_height.resize(_n);_height_count.resize(2*_n+1);_current.resize(_n);_active.resize(_n);_buckets.resize(2*_n+1);_queue.resize(_n);longlongarc_count=0;for(constauto&edges:_graph)arc_count+=int(edges.size());_work_limit=std::max(1LL,4*arc_count+_n);_parent.assign(_n,0);_cut_value.assign(_n,std::numeric_limits<Cap>::max());for(ints=1;s<_n;s++){intt=_parent[s];Capflow=max_flow(s,t);std::vector<bool>cut=source_side(s);for(intv=s+1;v<_n;v++){if(_parent[v]==t&&cut[v])_parent[v]=s;}if(cut[_parent[t]]){_parent[s]=_parent[t];_parent[t]=s;_cut_value[s]=_cut_value[t];_cut_value[t]=flow;}else{_cut_value[s]=flow;}}_tree.assign(_n,{});_tree_edges.clear();if(_n>0)_tree_edges.reserve(_n-1);for(intv=1;v<_n;v++){intp=_parent[v];Capcap=_cut_value[v];_tree_edges.push_back(Edge{v,p,cap});_tree[v].emplace_back(p,cap);_tree[p].emplace_back(v,cap);}build_query_table();_built=true;}conststd::vector<Edge>&tree_edges()const{assert(_built);return_tree_edges;}conststd::vector<int>&parent()const{assert(_built);return_parent;}conststd::vector<Cap>&cut_values()const{assert(_built);return_cut_value;}Capmin_cut(intu,intv)const{assert(_built);assert(0<=u&&u<_n);assert(0<=v&&v<_n);assert(u!=v);Capresult=std::numeric_limits<Cap>::max();if(_depth[u]<_depth[v])std::swap(u,v);intdifference=_depth[u]-_depth[v];for(intk=0;difference>0;k++,difference>>=1){if((difference&1)==0)continue;result=std::min(result,_minimum[k][u]);u=_up[k][u];}if(u==v)returnresult;for(intk=int(_up.size())-1;k>=0;k--){if(_up[k][u]==_up[k][v])continue;result=std::min(result,_minimum[k][u]);result=std::min(result,_minimum[k][v]);u=_up[k][u];v=_up[k][v];}result=std::min(result,_minimum[0][u]);result=std::min(result,_minimum[0][v]);returnresult;}};}// namespace flow}// namespace m1une#line 1 "graph/flow/min_cost_flow.hpp"
#line 6 "graph/flow/min_cost_flow.hpp"
#include<bit>
#line 15 "graph/flow/min_cost_flow.hpp"
#line 18 "graph/flow/min_cost_flow.hpp"
namespacem1une{namespaceflow{template<classCap,classCost>structMinCostFlow{structEdge{intfrom;intto;Capcap;Capflow;Costcost;};private:structInternalEdge{intto;intrev;Capcap;Costcost;};int_n;std::vector<std::pair<int,int>>_pos;std::vector<std::vector<InternalEdge>>_g;bool_has_negative_cost;bool_has_flow;template<classKey>structRadixHeap{usingUnsigned=std::make_unsigned_t<Key>;staticconstexprintbits=std::numeric_limits<Unsigned>::digits;std::array<std::vector<std::pair<Unsigned,int>>,bits+1>bucket;Unsignedlast=0;std::size_tcount=0;staticintindex(Unsignedfirst,Unsignedsecond){returnint(std::bit_width(first^second));}voidclear(){for(auto&values:bucket)values.clear();last=0;count=0;}boolempty()const{returncount==0;}voidpush(Keykey,intvertex){Unsignedvalue=static_cast<Unsigned>(key);assert(last<=value);bucket[index(value,last)].emplace_back(value,vertex);count++;}std::pair<Key,int>pop(){if(bucket[0].empty()){inti=1;while(bucket[i].empty())i++;last=bucket[i][0].first;for(constauto&value:bucket[i]){last=std::min(last,value.first);}for(constauto&value:bucket[i]){bucket[index(value.first,last)].push_back(value);}bucket[i].clear();}auto[key,vertex]=bucket[0].back();bucket[0].pop_back();count--;return{static_cast<Key>(key),vertex};}};template<classKey>structBinaryHeap{usingValue=std::pair<Key,int>;std::vector<Value>heap;voidclear(){heap.clear();}boolempty()const{returnheap.empty();}voidpush(Keykey,intvertex){heap.emplace_back(key,vertex);std::push_heap(heap.begin(),heap.end(),std::greater<Value>());}Valuepop(){std::pop_heap(heap.begin(),heap.end(),std::greater<Value>());Valueresult=heap.back();heap.pop_back();returnresult;}};template<classKey,boolUseRadix=std::numeric_limits<Key>::is_integer&&sizeof(Key)<=8>structHeapSelector{usingType=BinaryHeap<Key>;};template<classKey>structHeapSelector<Key,true>{usingType=RadixHeap<Key>;};booluse_network_simplex(ints,intt,Capflow_limit)const{if(_has_negative_cost)returnfalse;if(_pos.size()<64)returnfalse;autoadd_saturated=[](Capfirst,Capsecond){constCapmaximum=std::numeric_limits<Cap>::max();returnmaximum-first<second?maximum:first+second;};structTerminalCapacity{Captotal=Cap(0);std::array<Cap,7>largest{};};autoadd_capacity=[&](TerminalCapacity&terminal,Capcap){terminal.total=add_saturated(terminal.total,cap);for(Cap¤t:terminal.largest){if(cap<=current)break;std::swap(cap,current);}};TerminalCapacitysource;for(constauto&e:_g[s]){if(e.to==s)continue;add_capacity(source,e.cap);}TerminalCapacitysink;for(constauto&e:_g[t]){if(e.to==t)continue;Capcap=_g[e.to][e.rev].cap;add_capacity(sink,cap);}Captarget=std::min(flow_limit,std::min(source.total,sink.total));if(target==Cap(0))returnfalse;autorequires_eight_arcs=[&](constTerminalCapacity&terminal){Capsum=Cap(0);for(Capcap:terminal.largest){sum=add_saturated(sum,cap);}returnsum<target;};returnrequires_eight_arcs(source)&&requires_eight_arcs(sink);}std::pair<Cap,Cost>network_simplex_flow(ints,intt,Capflow_limit){structResidualArc{intedge;boolreverse;};usingSolver=BoundedMinCostFlow<Cap,Cost,Cost>;std::vector<ResidualArc>arcs;arcs.reserve(2*_pos.size());for(inti=0;i<int(_pos.size());i++){auto[from,idx]=_pos[i];constauto&e=_g[from][idx];constauto&reverse=_g[e.to][e.rev];if(e.cap!=Cap(0)){arcs.push_back(ResidualArc{i,false});}if(reverse.cap!=Cap(0)){arcs.push_back(ResidualArc{i,true});}}autoadd_saturated=[](Capfirst,Capsecond,bool&exact){constCapmaximum=std::numeric_limits<Cap>::max();if(maximum-first<second){exact=false;returnmaximum;}returnfirst+second;};boolsource_capacity_exact=true;Capsource_capacity=Cap(0);for(constauto&e:_g[s]){if(e.to==s)continue;source_capacity=add_saturated(source_capacity,e.cap,source_capacity_exact);}boolsink_capacity_exact=true;Capsink_capacity=Cap(0);for(constauto&e:_g[t]){if(e.to==t)continue;sink_capacity=add_saturated(sink_capacity,_g[e.to][e.rev].cap,sink_capacity_exact);}Captarget=std::min(flow_limit,std::min(source_capacity,sink_capacity));if(target==Cap(0))return{Cap(0),Cost(0)};structArcData{intfrom;intto;Capcap;Costcost;};autoarc_data=[&](constResidualArc&arc){auto[from,idx]=_pos[arc.edge];constauto&e=_g[from][idx];constauto&reverse=_g[e.to][e.rev];returnarc.reverse?ArcData{e.to,from,reverse.cap,reverse.cost}:ArcData{from,e.to,e.cap,e.cost};};autoapply_flow=[&](constResidualArc&arc,Capamount){auto[from,idx]=_pos[arc.edge];auto&e=_g[from][idx];auto&reverse=_g[e.to][e.rev];if(arc.reverse){reverse.cap-=amount;e.cap+=amount;}else{e.cap-=amount;reverse.cap+=amount;}};booltarget_infeasible=false;if(source_capacity_exact&&sink_capacity_exact&&target==source_capacity&&target==sink_capacity){Solverterminal_solver(_n);terminal_solver.reserve_edges(int(arcs.size()));std::vector<Cap>balance(_n,Cap(0));std::vector<int>internal_arcs;std::vector<int>fixed_arcs;internal_arcs.reserve(arcs.size());fixed_arcs.reserve(_g[s].size()+_g[t].size());Costfixed_cost=Cost(0);for(inti=0;i<int(arcs.size());i++){ArcDatadata=arc_data(arcs[i]);if(data.from==s){if(data.to==s)continue;fixed_arcs.push_back(i);fixed_cost+=Cost(data.cap)*data.cost;if(data.to!=t)balance[data.to]+=data.cap;}elseif(data.to==t){if(data.from==t)continue;fixed_arcs.push_back(i);fixed_cost+=Cost(data.cap)*data.cost;balance[data.from]-=data.cap;}elseif(data.to!=s&&data.from!=t){terminal_solver.add_edge(data.from,data.to,Cap(0),data.cap,data.cost);internal_arcs.push_back(i);}}autoterminal_result=terminal_solver.min_cost_flow(balance);if(terminal_result){for(inti:fixed_arcs){apply_flow(arcs[i],arc_data(arcs[i]).cap);}for(inti=0;i<int(internal_arcs.size());i++){apply_flow(arcs[internal_arcs[i]],terminal_result->flow(i));}_has_flow=true;return{target,fixed_cost+terminal_result->cost};}target_infeasible=true;}Solversolver(_n);solver.reserve_edges(int(arcs.size()));for(constauto&arc:arcs){ArcDatadata=arc_data(arc);solver.add_edge(data.from,data.to,Cap(0),data.cap,data.cost);}Capsent=target;std::optional<typenameSolver::Result>result;if(!target_infeasible&&target!=std::numeric_limits<Cap>::max()){result=solver.min_cost_st_flow(s,t,target);}if(!result){MaxFlow<Cap>feasible(_n);feasible.reserve_edges(int(arcs.size()));for(constauto&arc:arcs){auto[from,idx]=_pos[arc.edge];constauto&e=_g[from][idx];constauto&reverse=_g[e.to][e.rev];if(arc.reverse){feasible.add_edge(e.to,from,reverse.cap);}else{feasible.add_edge(from,e.to,e.cap);}}sent=feasible.max_flow(s,t,target);if(sent==Cap(0))return{Cap(0),Cost(0)};result=solver.min_cost_st_flow(s,t,sent);}assert(result.has_value());for(inti=0;i<int(arcs.size());i++){auto[from,idx]=_pos[arcs[i].edge];auto&e=_g[from][idx];auto&reverse=_g[e.to][e.rev];Capamount=result->flow(i);if(arcs[i].reverse){reverse.cap-=amount;e.cap+=amount;}else{e.cap-=amount;reverse.cap+=amount;}}_has_flow=true;return{sent,result->cost};}voidinit_potential(ints,std::vector<Cost>&potential,Costcost_inf)const{if(!_has_negative_cost&&!_has_flow){potential.assign(_n,Cost(0));return;}potential.assign(_n,cost_inf);potential[s]=Cost(0);for(intiter=0;iter<_n-1;iter++){boolupdated=false;for(intv=0;v<_n;v++){if(potential[v]==cost_inf)continue;for(constauto&e:_g[v]){if(e.cap==Cap(0))continue;Costnd=potential[v]+e.cost;if(nd<potential[e.to]){potential[e.to]=nd;updated=true;}}}if(!updated)break;}for(intv=0;v<_n;v++){if(potential[v]==cost_inf)potential[v]=Cost(0);}}public:MinCostFlow():MinCostFlow(0){}explicitMinCostFlow(intn):_n(n),_g(n),_has_negative_cost(false),_has_flow(false){assert(0<=n);}intsize()const{return_n;}intedge_count()const{returnint(_pos.size());}voidreserve_edges(intedge_count){assert(0<=edge_count);_pos.reserve(edge_count);if(_n==0||edge_count==0||2*std::size_t(edge_count)<std::size_t(_n)){return;}conststd::size_taverage_degree=(3*std::size_t(edge_count)+std::size_t(_n)-1)/std::size_t(_n);for(auto&edges:_g)edges.reserve(average_degree);}voidreserve_edges(intedge_count,conststd::vector<int>°rees){assert(0<=edge_count);assert(int(degrees.size())==_n);_pos.reserve(edge_count);for(intv=0;v<_n;v++){assert(0<=degrees[v]);_g[v].reserve(degrees[v]);}}intadd_edge(intfrom,intto,Capcap,Costcost){assert(0<=from&&from<_n);assert(0<=to&&to<_n);assert(Cap(0)<=cap);_has_negative_cost=_has_negative_cost||cost<Cost(0);intid=int(_pos.size());intfrom_id=int(_g[from].size());intto_id=int(_g[to].size());if(from==to)to_id++;_pos.emplace_back(from,from_id);_g[from].push_back(InternalEdge{to,to_id,cap,cost});_g[to].push_back(InternalEdge{from,from_id,Cap(0),-cost});returnid;}Edgeget_edge(inti)const{assert(0<=i&&i<int(_pos.size()));auto[from,idx]=_pos[i];constauto&e=_g[from][idx];constauto&re=_g[e.to][e.rev];returnEdge{from,e.to,e.cap+re.cap,re.cap,e.cost};}std::vector<Edge>edges()const{std::vector<Edge>result;result.reserve(_pos.size());for(inti=0;i<int(_pos.size());i++)result.push_back(get_edge(i));returnresult;}std::pair<Cap,Cost>flow(ints,intt){returnflow(s,t,std::numeric_limits<Cap>::max());}std::pair<Cap,Cost>flow(ints,intt,Capflow_limit){assert(0<=s&&s<_n);assert(0<=t&&t<_n);assert(s!=t);assert(Cap(0)<=flow_limit);if(flow_limit==Cap(0))return{Cap(0),Cost(0)};ifconstexpr(std::numeric_limits<Cap>::is_integer&&std::numeric_limits<Cap>::is_signed&&std::numeric_limits<Cost>::is_signed){if(use_network_simplex(s,t,flow_limit)){returnnetwork_simplex_flow(s,t,flow_limit);}}autoresult=slope(s,t,flow_limit);returnresult.back();}std::vector<std::pair<Cap,Cost>>slope(ints,intt){returnslope(s,t,std::numeric_limits<Cap>::max());}std::vector<std::pair<Cap,Cost>>slope(ints,intt,Capflow_limit){assert(0<=s&&s<_n);assert(0<=t&&t<_n);assert(s!=t);assert(Cap(0)<=flow_limit);constCostcost_inf=std::numeric_limits<Cost>::max()/Cost(4);std::vector<Cost>potential,dist(_n);std::vector<int>prev_v(_n),prev_e(_n);std::vector<int>settled;settled.reserve(_n);typenameHeapSelector<Cost>::Typeque;init_potential(s,potential,cost_inf);std::vector<std::pair<Cap,Cost>>result;result.emplace_back(Cap(0),Cost(0));Capflow=0;Costcost=0;while(flow<flow_limit){std::fill(dist.begin(),dist.end(),cost_inf);dist[s]=Cost(0);settled.clear();que.clear();que.push(Cost(0),s);while(!que.empty()){auto[d,v]=que.pop();if(dist[v]!=d)continue;settled.push_back(v);if(v==t)break;for(inti=0;i<int(_g[v].size());i++){constauto&e=_g[v][i];if(e.cap==Cap(0))continue;Costnd=d+e.cost+potential[v]-potential[e.to];if(nd>=dist[e.to])continue;dist[e.to]=nd;prev_v[e.to]=v;prev_e[e.to]=i;que.push(nd,e.to);}}if(dist[t]==cost_inf)break;for(intv:settled){potential[v]+=dist[v]-dist[t];}Capadd=flow_limit-flow;for(intv=t;v!=s;v=prev_v[v]){add=std::min(add,_g[prev_v[v]][prev_e[v]].cap);}Costpath_cost=potential[t]-potential[s];for(intv=t;v!=s;v=prev_v[v]){auto&e=_g[prev_v[v]][prev_e[v]];e.cap-=add;_g[e.to][e.rev].cap+=add;}flow+=add;cost+=Cost(add)*path_cost;result.emplace_back(flow,cost);}_has_flow=_has_flow||flow!=Cap(0);returnresult;}};}// namespace flow}// namespace m1une#line 9 "graph/flow/flow.hpp"
#line 1 "graph/grid.hpp"
#line 8 "graph/grid.hpp"
#line 10 "graph/grid.hpp"
namespacem1une{namespacegraph{structGrid{private:int_h;int_w;public:staticconstexprstd::array<int,4>di4={-1,0,1,0};staticconstexprstd::array<int,4>dj4={0,1,0,-1};staticconstexprstd::array<int,8>di8={-1,-1,-1,0,0,1,1,1};staticconstexprstd::array<int,8>dj8={-1,0,1,-1,1,-1,0,1};Grid():_h(0),_w(0){}Grid(inth,intw):_h(h),_w(w){assert(0<=h);assert(0<=w);}intheight()const{return_h;}intwidth()const{return_w;}intsize()const{return_h*_w;}boolempty()const{returnsize()==0;}boolinside(inti,intj)const{return0<=i&&i<_h&&0<=j&&j<_w;}intid(inti,intj)const{assert(inside(i,j));returni*_w+j;}std::pair<int,int>pos(intv)const{assert(0<=v&&v<size());return{v/_w,v%_w};}std::vector<std::pair<int,int>>adj4(inti,intj)const{assert(inside(i,j));std::vector<std::pair<int,int>>result;result.reserve(4);for(intk=0;k<4;k++){intni=i+di4[k],nj=j+dj4[k];if(inside(ni,nj))result.emplace_back(ni,nj);}returnresult;}std::vector<std::pair<int,int>>adj8(inti,intj)const{assert(inside(i,j));std::vector<std::pair<int,int>>result;result.reserve(8);for(intk=0;k<8;k++){intni=i+di8[k],nj=j+dj8[k];if(inside(ni,nj))result.emplace_back(ni,nj);}returnresult;}std::vector<int>adj4_ids(intv)const{auto[i,j]=pos(v);std::vector<int>result;result.reserve(4);for(auto[ni,nj]:adj4(i,j))result.push_back(id(ni,nj));returnresult;}std::vector<int>adj8_ids(intv)const{auto[i,j]=pos(v);std::vector<int>result;result.reserve(8);for(auto[ni,nj]:adj8(i,j))result.push_back(id(ni,nj));returnresult;}Graph<int>graph4()const{returngraph4([](int,int){returntrue;});}Graph<int>graph8()const{returngraph8([](int,int){returntrue;});}template<classPassable>Graph<int>graph4(Passablepassable)const{Graph<int>g(size());for(inti=0;i<_h;i++){for(intj=0;j<_w;j++){if(!passable(i,j))continue;intv=id(i,j);for(auto[ni,nj]:adj4(i,j)){if(!passable(ni,nj))continue;intto=id(ni,nj);if(v<to)g.add_edge(v,to);}}}returng;}template<classPassable>Graph<int>graph8(Passablepassable)const{Graph<int>g(size());for(inti=0;i<_h;i++){for(intj=0;j<_w;j++){if(!passable(i,j))continue;intv=id(i,j);for(auto[ni,nj]:adj8(i,j)){if(!passable(ni,nj))continue;intto=id(ni,nj);if(v<to)g.add_edge(v,to);}}}returng;}};}// namespace graph}// namespace m1une#line 1 "graph/range_edge_graph.hpp"
#line 6 "graph/range_edge_graph.hpp"
#line 8 "graph/range_edge_graph.hpp"
namespacem1une{namespacegraph{structRangeEdgeNode{intvertex;intleft;intright;};template<classT>classRangeEdgeGraph{structSegmentNode{intleft=0;intright=0;intfrom_vertex=-1;intto_vertex=-1;};int_n;Graph<T>_graph;std::vector<SegmentNode>_segment;voidassert_point(intpoint)const{(void)point;assert(0<=point&&point<_n);}voidassert_range(intleft,intright)const{(void)left;(void)right;assert(0<=left&&left<=right&&right<=_n);}voidbuild(intnode,intleft,intright){_segment[node].left=left;_segment[node].right=right;if(right-left==1){_segment[node].from_vertex=left;_segment[node].to_vertex=left;return;}intmiddle=(left+right)/2;build(node*2,left,middle);build(node*2+1,middle,right);intfrom_vertex=_graph.add_vertex();intto_vertex=_graph.add_vertex();_segment[node].from_vertex=from_vertex;_segment[node].to_vertex=to_vertex;_graph.add_directed_edge(_segment[node*2].from_vertex,from_vertex,T());_graph.add_directed_edge(_segment[node*2+1].from_vertex,from_vertex,T());_graph.add_directed_edge(to_vertex,_segment[node*2].to_vertex,T());_graph.add_directed_edge(to_vertex,_segment[node*2+1].to_vertex,T());}voidcollect(intnode,intleft,intright,boolfrom_side,std::vector<RangeEdgeNode>&result)const{constauto¤t=_segment[node];if(right<=current.left||current.right<=left)return;if(left<=current.left&¤t.right<=right){intvertex=from_side?current.from_vertex:current.to_vertex;result.push_back(RangeEdgeNode{vertex,current.left,current.right});return;}collect(node*2,left,right,from_side,result);collect(node*2+1,left,right,from_side,result);}public:RangeEdgeGraph():RangeEdgeGraph(0){}explicitRangeEdgeGraph(intpoint_count):_n(point_count),_graph(point_count),_segment(point_count==0?1:point_count*4){assert(point_count>=0);if(point_count!=0)build(1,0,point_count);}intsize()const{return_n;}intpoint_vertex(intpoint)const{assert_point(point);returnpoint;}intadd_vertex(){return_graph.add_vertex();}Graph<T>&graph(){return_graph;}constGraph<T>&graph()const{return_graph;}std::vector<RangeEdgeNode>from_range_nodes(intleft,intright)const{assert_range(left,right);std::vector<RangeEdgeNode>result;if(left!=right)collect(1,left,right,true,result);returnresult;}std::vector<RangeEdgeNode>to_range_nodes(intleft,intright)const{assert_range(left,right);std::vector<RangeEdgeNode>result;if(left!=right)collect(1,left,right,false,result);returnresult;}intadd_point_to_point(intfrom,intto,Tcost){assert_point(from);assert_point(to);return_graph.add_directed_edge(from,to,cost);}voidadd_point_to_range(intfrom,intleft,intright,Tcost){assert_point(from);for(constauto&node:to_range_nodes(left,right)){_graph.add_directed_edge(from,node.vertex,cost);}}voidadd_range_to_point(intleft,intright,intto,Tcost){assert_point(to);for(constauto&node:from_range_nodes(left,right)){_graph.add_directed_edge(node.vertex,to,cost);}}intadd_range_to_range(intfrom_left,intfrom_right,intto_left,intto_right,Tcost){assert_range(from_left,from_right);assert_range(to_left,to_right);if(from_left==from_right||to_left==to_right)return-1;intauxiliary=add_vertex();for(constauto&node:from_range_nodes(from_left,from_right)){_graph.add_directed_edge(node.vertex,auxiliary,cost);}for(constauto&node:to_range_nodes(to_left,to_right)){_graph.add_directed_edge(auxiliary,node.vertex,T());}returnauxiliary;}};}// namespace graph}// namespace m1une#line 1 "graph/replacement_paths.hpp"
#line 11 "graph/replacement_paths.hpp"
#line 14 "graph/replacement_paths.hpp"
namespacem1une{namespacegraph{structGraphPath{std::vector<int>vertices;std::vector<int>edges;};template<classT>structEdgeReplacementPathsResult{GraphPathpath;std::vector<T>replacement_dist;Tinf;boolreachable(intpath_edge_index)const{assert(0<=path_edge_index&&path_edge_index<int(replacement_dist.size()));returnreplacement_dist[path_edge_index]!=inf;}};template<classT>structVertexReplacementPathsResult{GraphPathpath;std::vector<T>replacement_dist;Tinf;boolreachable(intpath_vertex_index)const{assert(0<=path_vertex_index&&path_vertex_index<int(replacement_dist.size()));returnreplacement_dist[path_vertex_index]!=inf;}};namespaceinternal{template<classT>Treplacement_paths_safe_add(Ta,Tb,Tinf){if(a>=inf||b>=inf)returninf;if(a>inf-b)returninf;returna+b;}template<classT>DijkstraResult<T>replacement_paths_dijkstra(constGraph<T>&g,ints,Tinf){intn=g.size();assert(0<=s&&s<n);DijkstraResult<T>result;result.dist.assign(n,inf);result.reached.assign(n,false);result.parent.assign(n,-1);result.parent_edge.assign(n,-1);result.inf=inf;usingP=std::pair<T,int>;std::priority_queue<P,std::vector<P>,std::greater<P>>que;result.dist[s]=T(0);result.reached[s]=true;que.emplace(T(0),s);while(!que.empty()){auto[d,v]=que.top();que.pop();if(result.dist[v]!=d)continue;for(constauto&e:g[v]){if(!e.alive)continue;Tnd=replacement_paths_safe_add(d,e.cost,inf);if(result.dist[e.to]<=nd)continue;result.reached[e.to]=true;result.dist[e.to]=nd;result.parent[e.to]=v;result.parent_edge[e.to]=e.id;que.emplace(nd,e.to);}}returnresult;}template<classT>std::vector<Edge<T>>replacement_paths_validate_graph(constGraph<T>&g,Tinf){assert(T(0)<inf);std::vector<int>occurrence(g.edge_count(),0);std::vector<Edge<T>>edge_by_id(g.edge_count());for(intv=0;v<g.size();v++){for(constauto&e:g[v]){assert(e.from==v);assert(0<=e.to&&e.to<g.size());assert(0<=e.id&&e.id<g.edge_count());if(e.alive)assert(T(0)<e.cost);if(occurrence[e.id]==0){edge_by_id[e.id]=e;}else{assert(occurrence[e.id]==1);constauto&other=edge_by_id[e.id];assert(e.from==other.to&&e.to==other.from);assert(e.cost==other.cost&&e.alive==other.alive);}occurrence[e.id]++;}}for(intid=0;id<g.edge_count();id++){// add_edge creates exactly two mutually reversed arcs with one logical id.assert(occurrence[id]==2);}returnedge_by_id;}template<classT>voidreplacement_paths_validate_path(constGraph<T>&g,constGraphPath&path,conststd::vector<Edge<T>>&edge_by_id,constDijkstraResult<T>&from_s,Tinf){assert(!path.vertices.empty());assert(path.edges.size()+1==path.vertices.size());std::vector<char>used_vertex(g.size(),false);for(intv:path.vertices){assert(0<=v&&v<g.size());assert(!used_vertex[v]);used_vertex[v]=true;}Tpath_cost=T(0);for(inti=0;i<int(path.edges.size());i++){intid=path.edges[i];assert(0<=id&&id<g.edge_count());assert(g.is_edge_alive(id));constauto&e=edge_by_id[id];intu=path.vertices[i];intv=path.vertices[i+1];assert((e.from==u&&e.to==v)||(e.from==v&&e.to==u));assert(T(0)<e.cost);path_cost=replacement_paths_safe_add(path_cost,e.cost,inf);}assert(from_s.reachable(path.vertices.back()));assert(path_cost==from_s.dist[path.vertices.back()]);}template<classT>GraphPathreplacement_paths_restore_path(constDijkstraResult<T>&result,ints,intt){assert(result.reachable(t));GraphPathpath;for(intv=t;v!=s;v=result.parent[v]){assert(v!=-1&&result.parent[v]!=-1&&result.parent_edge[v]!=-1);path.vertices.push_back(v);path.edges.push_back(result.parent_edge[v]);}path.vertices.push_back(s);std::reverse(path.vertices.begin(),path.vertices.end());std::reverse(path.edges.begin(),path.edges.end());returnpath;}template<classT>structReplacementPathsData{GraphPathpath;std::vector<T>dist_s;std::vector<T>dist_t;std::vector<int>block;std::vector<char>is_path_edge;std::vector<Edge<T>>edge_by_id;Tinf;};template<classT>ReplacementPathsData<T>replacement_paths_prepare(constGraph<T>&g,constGraphPath&path,Tinf,constDijkstraResult<T>*known_from_s){autoedge_by_id=replacement_paths_validate_graph(g,inf);ints=path.vertices.front();intt=path.vertices.back();autocomputed_from_s=known_from_s==nullptr?replacement_paths_dijkstra(g,s,inf):DijkstraResult<T>();constauto&from_s=known_from_s==nullptr?computed_from_s:*known_from_s;replacement_paths_validate_path(g,path,edge_by_id,from_s,inf);autofrom_t=replacement_paths_dijkstra(g,t,inf);intn=g.size();std::vector<int>path_position(n,-1);std::vector<char>is_path_edge(g.edge_count(),false);for(inti=0;i<int(path.vertices.size());i++)path_position[path.vertices[i]]=i;for(intid:path.edges)is_path_edge[id]=true;std::vector<int>parent(n,-1);for(inti=0;i<int(path.edges.size());i++){intv=path.vertices[i+1];parent[v]=path.vertices[i];constauto&e=edge_by_id[path.edges[i]];assert(replacement_paths_safe_add(from_s.dist[parent[v]],e.cost,inf)==from_s.dist[v]);}for(intv=0;v<n;v++){if(!from_s.reachable(v)||v==s||path_position[v]!=-1)continue;for(constauto&e:g[v]){if(!e.alive||!from_s.reachable(e.to))continue;if(replacement_paths_safe_add(from_s.dist[e.to],e.cost,inf)!=from_s.dist[v]){continue;}parent[v]=e.to;break;}assert(parent[v]!=-1);assert(from_s.dist[parent[v]]<from_s.dist[v]);}std::vector<std::vector<int>>children(n);for(intv=0;v<n;v++){if(parent[v]!=-1)children[parent[v]].push_back(v);}std::vector<int>block(n,-1);block[s]=0;std::vector<int>stack={s};while(!stack.empty()){intv=stack.back();stack.pop_back();for(intto:children[v]){block[to]=path_position[to]==-1?block[v]:path_position[to];stack.push_back(to);}}for(intv=0;v<n;v++)assert(!from_s.reachable(v)||block[v]!=-1);return{path,from_s.dist,from_t.dist,block,is_path_edge,edge_by_id,inf};}template<classT>classReplacementPathsRangeChmin{private:int_size;std::vector<T>_lazy;public:ReplacementPathsRangeChmin(intn,Tinf):_size(1){while(_size<n)_size<<=1;_lazy.assign(2*_size,inf);}voidapply(intl,intr,Tvalue){assert(0<=l&&l<=r&&r<=_size);for(l+=_size,r+=_size;l<r;l>>=1,r>>=1){if(l&1){_lazy[l]=std::min(_lazy[l],value);l++;}if(r&1){--r;_lazy[r]=std::min(_lazy[r],value);}}}std::vector<T>values(intn){for(intv=1;v<_size;v++){_lazy[2*v]=std::min(_lazy[2*v],_lazy[v]);_lazy[2*v+1]=std::min(_lazy[2*v+1],_lazy[v]);}returnstd::vector<T>(_lazy.begin()+_size,_lazy.begin()+_size+n);}};template<classT>std::vector<T>replacement_paths_solve_edges(constReplacementPathsData<T>&data){intanswer_size=int(data.path.edges.size());ReplacementPathsRangeChmin<T>range_chmin(answer_size,data.inf);for(constauto&e:data.edge_by_id){if(!e.alive||data.is_path_edge[e.id])continue;intu=e.from;intv=e.to;if(data.block[u]==-1||data.block[v]==-1||data.block[u]==data.block[v])continue;if(data.block[u]>data.block[v])std::swap(u,v);inta=data.block[u];intb=data.block[v];Tcandidate=replacement_paths_safe_add(data.dist_s[u],e.cost,data.inf);candidate=replacement_paths_safe_add(candidate,data.dist_t[v],data.inf);if(candidate==data.inf)continue;range_chmin.apply(a,b,candidate);}returnrange_chmin.values(answer_size);}template<classT>Treplacement_paths_without_vertex(constGraph<T>&g,ints,intt,intremoved,Tinf){if(s==removed||t==removed)returninf;std::vector<T>dist(g.size(),inf);usingP=std::pair<T,int>;std::priority_queue<P,std::vector<P>,std::greater<P>>que;dist[s]=T(0);que.emplace(T(0),s);while(!que.empty()){auto[d,v]=que.top();que.pop();if(dist[v]!=d)continue;for(constauto&e:g[v]){if(!e.alive||e.to==removed)continue;Tnd=replacement_paths_safe_add(d,e.cost,inf);if(dist[e.to]<=nd)continue;dist[e.to]=nd;que.emplace(nd,e.to);}}returndist[t];}template<classT>std::vector<T>replacement_paths_solve_vertices(constGraph<T>&g,constReplacementPathsData<T>&data){// One edge can cross an edge cut, but a vertex-avoiding path may enter and// leave the failed vertex's tree block through two different detour edges.intpath_size=int(data.path.vertices.size());std::vector<T>answer(path_size,data.inf);ints=data.path.vertices.front();intt=data.path.vertices.back();for(inti=1;i+1<path_size;i++){answer[i]=replacement_paths_without_vertex(g,s,t,data.path.vertices[i],data.inf);}returnanswer;}}// namespace internaltemplate<classT>EdgeReplacementPathsResult<T>edge_replacement_paths(constGraph<T>&g,constGraphPath&path,Tinf=std::numeric_limits<T>::max()/T(4)){assert(!path.vertices.empty());autodata=internal::replacement_paths_prepare(g,path,inf,static_cast<constDijkstraResult<T>*>(nullptr));autoreplacement_dist=internal::replacement_paths_solve_edges(data);return{path,replacement_dist,inf};}template<classT>EdgeReplacementPathsResult<T>edge_replacement_paths(constGraph<T>&g,ints,intt,Tinf=std::numeric_limits<T>::max()/T(4)){assert(0<=s&&s<g.size());assert(0<=t&&t<g.size());autofrom_s=internal::replacement_paths_dijkstra(g,s,inf);assert(from_s.reachable(t));autopath=internal::replacement_paths_restore_path(from_s,s,t);autodata=internal::replacement_paths_prepare(g,path,inf,&from_s);autoreplacement_dist=internal::replacement_paths_solve_edges(data);return{path,replacement_dist,inf};}template<classT>VertexReplacementPathsResult<T>vertex_replacement_paths(constGraph<T>&g,constGraphPath&path,Tinf=std::numeric_limits<T>::max()/T(4)){assert(!path.vertices.empty());autodata=internal::replacement_paths_prepare(g,path,inf,static_cast<constDijkstraResult<T>*>(nullptr));autoreplacement_dist=internal::replacement_paths_solve_vertices(g,data);return{path,replacement_dist,inf};}template<classT>VertexReplacementPathsResult<T>vertex_replacement_paths(constGraph<T>&g,ints,intt,Tinf=std::numeric_limits<T>::max()/T(4)){assert(0<=s&&s<g.size());assert(0<=t&&t<g.size());autofrom_s=internal::replacement_paths_dijkstra(g,s,inf);assert(from_s.reachable(t));autopath=internal::replacement_paths_restore_path(from_s,s,t);autodata=internal::replacement_paths_prepare(g,path,inf,&from_s);autoreplacement_dist=internal::replacement_paths_solve_vertices(g,data);return{path,replacement_dist,inf};}}// namespace graph}// namespace m1une#line 1 "graph/tree/all.hpp"
#line 1 "graph/tree/cartesian_tree.hpp"
#line 10 "graph/tree/cartesian_tree.hpp"
#line 12 "graph/tree/cartesian_tree.hpp"
namespacem1une{namespacetree{structCartesianTree{introot;std::vector<int>parent;std::vector<int>left;std::vector<int>right;private:int_n;voidcheck_vertex(intv)const{assert(0<=v&&v<_n);}public:CartesianTree():root(-1),_n(0){}template<classT,classCompare=std::less<T>>explicitCartesianTree(conststd::vector<T>&a,Comparecomp=Compare()):root(-1),_n(0){build(a,comp);}template<classT,classCompare=std::less<T>>voidbuild(conststd::vector<T>&a,Comparecomp=Compare()){assert(a.size()<=static_cast<std::size_t>(std::numeric_limits<int>::max()));_n=int(a.size());root=-1;parent.assign(_n,-1);left.assign(_n,-1);right.assign(_n,-1);std::vector<int>stack;stack.reserve(_n);for(inti=0;i<_n;i++){intlast=-1;while(!stack.empty()&&comp(a[i],a[stack.back()])){last=stack.back();stack.pop_back();}if(last!=-1){left[i]=last;parent[last]=i;}if(!stack.empty()){right[stack.back()]=i;parent[i]=stack.back();}stack.push_back(i);}if(!stack.empty())root=stack.front();}intsize()const{return_n;}boolempty()const{return_n==0;}intparent_or_self(intv)const{check_vertex(v);returnparent[v]==-1?v:parent[v];}std::vector<int>parent_with_root_self()const{std::vector<int>result=parent;if(root!=-1)result[root]=root;returnresult;}std::vector<std::pair<int,int>>edges()const{std::vector<std::pair<int,int>>result;if(_n==0)returnresult;result.reserve(_n-1);for(intv=0;v<_n;v++){if(parent[v]!=-1)result.emplace_back(parent[v],v);}returnresult;}m1une::graph::Graph<int>to_graph()const{m1une::graph::Graph<int>g(_n);for(intv=0;v<_n;v++){if(parent[v]!=-1)g.add_edge(parent[v],v);}returng;}};template<classT,classCompare=std::less<T>>CartesianTreecartesian_tree(conststd::vector<T>&a,Comparecomp=Compare()){CartesianTreeresult;result.build(a,comp);returnresult;}}// namespace tree}// namespace m1une#line 1 "graph/tree/centroid_decomposition.hpp"
#line 6 "graph/tree/centroid_decomposition.hpp"
#line 8 "graph/tree/centroid_decomposition.hpp"
namespacem1une{namespacetree{template<classT=int>structCentroidDecomposition{intn;std::vector<int>parent;std::vector<int>depth;std::vector<int>order;std::vector<int>roots;std::vector<std::vector<int>>children;private:std::vector<int>_subtree_size;std::vector<int>_work_parent;std::vector<char>_removed;voidbuild_component(constm1une::graph::Graph<T>&g,intstart,intp,intd){std::vector<int>nodes;std::vector<int>stack={start};_work_parent[start]=-2;while(!stack.empty()){intv=stack.back();stack.pop_back();nodes.push_back(v);for(constauto&e:g[v]){if(!e.alive||_removed[e.to])continue;if(_work_parent[e.to]!=-1)continue;_work_parent[e.to]=v;stack.push_back(e.to);}}for(intv:nodes)_subtree_size[v]=1;for(inti=int(nodes.size())-1;i>=0;i--){intv=nodes[i];if(_work_parent[v]>=0)_subtree_size[_work_parent[v]]+=_subtree_size[v];}inttotal=int(nodes.size());intcentroid=start;intbest=total+1;for(intv:nodes){intlargest=total-_subtree_size[v];for(constauto&e:g[v]){if(!e.alive||_removed[e.to])continue;if(_work_parent[e.to]==v)largest=std::max(largest,_subtree_size[e.to]);}if(largest<best){best=largest;centroid=v;}}for(intv:nodes)_work_parent[v]=-1;parent[centroid]=p;depth[centroid]=d;order.push_back(centroid);if(p==-1){roots.push_back(centroid);}else{children[p].push_back(centroid);}_removed[centroid]=true;for(constauto&e:g[centroid]){if(!e.alive||_removed[e.to])continue;build_component(g,e.to,centroid,d+1);}}public:CentroidDecomposition():n(0){}explicitCentroidDecomposition(constm1une::graph::Graph<T>&g){build(g);}voidbuild(constm1une::graph::Graph<T>&g){n=g.size();parent.assign(n,-1);depth.assign(n,-1);order.clear();order.reserve(n);roots.clear();children.assign(n,{});_subtree_size.assign(n,0);_work_parent.assign(n,-1);_removed.assign(n,false);for(intv=0;v<n;v++){if(depth[v]==-1)build_component(g,v,-1,0);}}intsize()const{returnn;}boolempty()const{returnn==0;}introot()const{returnroots.empty()?-1:roots[0];}};}// namespace tree}// namespace m1une#line 1 "graph/tree/cumulative_sum.hpp"
#line 8 "graph/tree/cumulative_sum.hpp"
#line 1 "monoid/add.hpp"
namespacem1une{namespacemonoid{// Monoid for addition (Range Sum).template<typenameT>structAdd{usingvalue_type=T;staticconstexprboolcommutative=true;// Returns the identity element for addition, which is 0.staticconstexprTid(){returnT(0);}// Returns the sum of a and b.staticconstexprTop(constT&a,constT&b){returna+b;}staticconstexprTinv(constT&x){return-x;}};}// namespace monoid}// namespace m1une#line 1 "monoid/concept.hpp"
#line 5 "monoid/concept.hpp"
namespacem1une{namespacemonoid{// Concept to check if a type satisfies the requirements of a Monoid.// A Monoid must have a `value_type`, an identity element `id()`, and an associative binary operation `op()`.template<typenameM>conceptIsMonoid=requires(typenameM::value_typea,typenameM::value_typeb){// 1. Must define `value_type`typenameM::value_type;// 2. Must have a static method `id()` returning `value_type`{M::id()}->std::same_as<typenameM::value_type>;// 3. Must have a static method `op(a, b)` returning `value_type`{M::op(a,b)}->std::same_as<typenameM::value_type>;};// Concept for groups. A type satisfying this concept must also obey the group// laws; concepts can check the interface but not the algebraic properties.template<typenameM>conceptIsGroup=IsMonoid<M>&&requires(typenameM::value_typea){{M::inv(a)}->std::same_as<typenameM::value_type>;};// Concept for commutative groups. Commutativity is a semantic requirement and// cannot be checked by a C++ concept.template<typenameM>conceptIsCommutativeGroup=IsGroup<M>;}// namespace monoid}// namespace m1une#line 12 "graph/tree/cumulative_sum.hpp"
namespacem1une{namespacetree{// Static cumulative products on root paths. Values are attached to vertices by// default; set EdgeValues to true to index them by graph edge id instead.template<m1une::monoid::IsCommutativeGroupGroup,boolEdgeValues=false>classTreeCumulativeProduct{public:usingvalue_type=typenameGroup::value_type;private:int_n=0;int_root=-1;std::vector<int>_parent;std::vector<int>_depth;std::vector<int>_head;std::vector<value_type>_prefix;voidcheck_vertex(intvertex)const{assert(0<=vertex&&vertex<_n);}public:TreeCumulativeProduct()=default;template<classEdgeCost>explicitTreeCumulativeProduct(constm1une::graph::Graph<EdgeCost>&graph,conststd::vector<value_type>&values,introot=0){build(graph,values,root);}template<classEdgeCost>voidbuild(constm1une::graph::Graph<EdgeCost>&graph,conststd::vector<value_type>&values,introot=0){_n=graph.size();_root=_n==0?-1:root;assert(int(values.size())==(EdgeValues?graph.edge_count():graph.size()));_parent.assign(_n,-2);_depth.assign(_n,0);_head.assign(_n,-1);_prefix.assign(_n,Group::id());if(_n==0)return;assert(0<=root&&root<_n);std::vector<int>parent_edge(_n,-1);std::vector<int>order;order.reserve(_n);std::vector<int>stack={root};_parent[root]=-1;while(!stack.empty()){intvertex=stack.back();stack.pop_back();order.push_back(vertex);for(constauto&edge:graph[vertex]){if(!edge.alive||_parent[edge.to]!=-2)continue;_parent[edge.to]=vertex;parent_edge[edge.to]=edge.id;_depth[edge.to]=_depth[vertex]+1;stack.push_back(edge.to);}}assert(int(order.size())==_n);std::vector<int>subtree_size(_n,1);std::vector<int>heavy(_n,-1);for(intindex=_n-1;index>0;index--){intvertex=order[index];intparent=_parent[vertex];subtree_size[parent]+=subtree_size[vertex];if(heavy[parent]==-1||subtree_size[heavy[parent]]<subtree_size[vertex]){heavy[parent]=vertex;}}std::vector<std::pair<int,int>>starts;starts.emplace_back(root,root);while(!starts.empty()){auto[start,head]=starts.back();starts.pop_back();for(intvertex=start;vertex!=-1;vertex=heavy[vertex]){_head[vertex]=head;for(constauto&edge:graph[vertex]){if(edge.alive&&_parent[edge.to]==vertex&&edge.to!=heavy[vertex]){starts.emplace_back(edge.to,edge.to);}}}}ifconstexpr(!EdgeValues)_prefix[root]=values[root];for(intvertex:order){if(vertex==root)continue;ifconstexpr(EdgeValues){assert(0<=parent_edge[vertex]);_prefix[vertex]=Group::op(_prefix[_parent[vertex]],values[parent_edge[vertex]]);}else{_prefix[vertex]=Group::op(_prefix[_parent[vertex]],values[vertex]);}}}intsize()const{return_n;}boolempty()const{return_n==0;}introot()const{return_root;}intlca(intfirst,intsecond)const{check_vertex(first);check_vertex(second);while(_head[first]!=_head[second]){if(_depth[_head[first]]<_depth[_head[second]]){std::swap(first,second);}first=_parent[_head[first]];}return_depth[first]<_depth[second]?first:second;}// Product on the root-to-vertex path. The root vertex is included for// vertex values; no edge lies above it in edge-value mode.value_typeprod(intvertex)const{check_vertex(vertex);return_prefix[vertex];}// Product on the simple path from first to second. Both endpoints are// included for vertex values.value_typeprod(intfirst,intsecond)const{intancestor=lca(first,second);value_typeresult=Group::op(_prefix[first],_prefix[second]);result=Group::op(result,Group::inv(_prefix[ancestor]));ifconstexpr(EdgeValues){result=Group::op(result,Group::inv(_prefix[ancestor]));}elseif(_parent[ancestor]!=-1){result=Group::op(result,Group::inv(_prefix[_parent[ancestor]]));}returnresult;}};template<m1une::monoid::IsCommutativeGroupGroup>usingTreeEdgeCumulativeProduct=TreeCumulativeProduct<Group,true>;template<classT,boolEdgeValues=false>classTreeCumulativeSum:publicTreeCumulativeProduct<m1une::monoid::Add<T>,EdgeValues>{private:usingBase=TreeCumulativeProduct<m1une::monoid::Add<T>,EdgeValues>;public:usingBase::Base;Tsum(intvertex)const{returnBase::prod(vertex);}Tsum(intfirst,intsecond)const{returnBase::prod(first,second);}};template<classT>usingTreeEdgeCumulativeSum=TreeCumulativeSum<T,true>;}// namespace tree}// namespace m1une#line 1 "graph/tree/diameter.hpp"
#line 6 "graph/tree/diameter.hpp"
#line 8 "graph/tree/diameter.hpp"
namespacem1une{namespacetree{template<classT=int>structTreeDiameter{Tcost;intedge_count;intfrom;intto;std::vector<int>vertices;std::vector<int>edge_ids;boolempty()const{returnvertices.empty();}};namespaceinternal{template<classT>structFarthestResult{intvertex;std::vector<char>seen;std::vector<T>dist;std::vector<int>parent;std::vector<int>parent_edge;};template<classT>FarthestResult<T>farthest_from(constm1une::graph::Graph<T>&g,intstart){intn=g.size();FarthestResult<T>result;result.vertex=start;result.seen.assign(n,false);result.dist.assign(n,T(0));result.parent.assign(n,-1);result.parent_edge.assign(n,-1);std::vector<int>stack={start};result.seen[start]=true;while(!stack.empty()){intv=stack.back();stack.pop_back();if(result.dist[result.vertex]<result.dist[v])result.vertex=v;for(constauto&e:g[v]){if(!e.alive)continue;if(result.seen[e.to])continue;result.seen[e.to]=true;result.dist[e.to]=result.dist[v]+e.cost;result.parent[e.to]=v;result.parent_edge[e.to]=e.id;stack.push_back(e.to);}}returnresult;}}// namespace internaltemplate<classT>TreeDiameter<T>tree_diameter(constm1une::graph::Graph<T>&g){intn=g.size();TreeDiameter<T>best;best.cost=T(0);best.edge_count=0;best.from=-1;best.to=-1;if(n==0)returnbest;std::vector<char>done(n,false);for(intstart=0;start<n;start++){if(done[start])continue;autofirst=internal::farthest_from(g,start);for(intv=0;v<n;v++){if(first.seen[v])done[v]=true;}autosecond=internal::farthest_from(g,first.vertex);inta=first.vertex;intb=second.vertex;Tcost=second.dist[b];if(best.from!=-1&&!(best.cost<cost))continue;best.cost=cost;best.from=a;best.to=b;best.vertices.clear();best.edge_ids.clear();for(intv=b;v!=-1;v=second.parent[v]){best.vertices.push_back(v);if(v!=a)best.edge_ids.push_back(second.parent_edge[v]);}std::reverse(best.vertices.begin(),best.vertices.end());std::reverse(best.edge_ids.begin(),best.edge_ids.end());best.edge_count=int(best.edge_ids.size());}returnbest;}}// namespace tree}// namespace m1une#line 1 "graph/tree/distance_frequency.hpp"
#line 10 "graph/tree/distance_frequency.hpp"
#line 14 "graph/tree/distance_frequency.hpp"
namespacem1une{namespacetree{namespacedistance_frequency_detail{template<classMint,classT>std::vector<Mint>count_ordered_pairs(constm1une::graph::Graph<T>&tree,constCentroidDecomposition<T>&decomposition){constintsize=tree.size();std::vector<Mint>count(static_cast<std::size_t>(size));std::vector<char>removed(std::size_t(size),false);std::vector<Mint>histogram;std::vector<std::pair<int,int>>stack;std::vector<int>parent(std::size_t(size),-1);for(intcentroid:decomposition.order){std::vector<Mint>total(1,Mint(1));for(constauto&edge:tree[centroid]){if(!edge.alive||removed[std::size_t(edge.to)])continue;histogram.clear();stack.clear();stack.emplace_back(edge.to,1);parent[std::size_t(edge.to)]=centroid;while(!stack.empty()){constauto[vertex,distance]=stack.back();stack.pop_back();if(int(histogram.size())<=distance){histogram.resize(std::size_t(distance+1));}histogram[std::size_t(distance)]+=Mint(1);for(constauto&next:tree[vertex]){if(!next.alive||removed[std::size_t(next.to)])continue;if(next.to==parent[std::size_t(vertex)])continue;parent[std::size_t(next.to)]=vertex;stack.emplace_back(next.to,distance+1);}}if(total.size()<histogram.size()){total.resize(histogram.size());}for(std::size_tdistance=0;distance<histogram.size();distance++){total[distance]+=histogram[distance];}conststd::vector<Mint>within_component=m1une::fps::convolution(histogram,histogram);conststd::size_tlimit=std::min(count.size(),within_component.size());for(std::size_tdistance=0;distance<limit;distance++){count[distance]-=within_component[distance];}}conststd::vector<Mint>through_centroid=m1une::fps::convolution(total,total);conststd::size_tlimit=std::min(count.size(),through_centroid.size());for(std::size_tdistance=0;distance<limit;distance++){count[distance]+=through_centroid[distance];}removed[std::size_t(centroid)]=true;}returncount;}inlinestd::uint64_tcombine_residues(std::uint32_tfirst,std::uint32_tsecond){usingFirst=m1une::math::ModInt<998244353>;usingSecond=m1une::math::ModInt<924844033>;staticconststd::uint64_tinverse=Second(First::mod()).inv().val();conststd::uint64_toffset=(std::uint64_t(second)+Second::mod()-first%Second::mod())%Second::mod();conststd::uint64_tmultiplier=offset*inverse%Second::mod();returnstd::uint64_t(first)+std::uint64_t(First::mod())*multiplier;}}// namespace distance_frequency_detailtemplate<classT>std::vector<longlong>tree_distance_frequency(constm1une::graph::Graph<T>&tree){constintsize=tree.size();assert(tree.edge_count()==std::max(0,size-1));if(size==0)return{};constCentroidDecomposition<T>decomposition(tree);assert(decomposition.roots.size()==1);usingFirst=m1une::math::ModInt<998244353>;usingSecond=m1une::math::ModInt<924844033>;assert(std::uint64_t(size)*std::uint64_t(size-1)<std::uint64_t(First::mod())*Second::mod());conststd::vector<First>first=distance_frequency_detail::count_ordered_pairs<First>(tree,decomposition);conststd::vector<Second>second=distance_frequency_detail::count_ordered_pairs<Second>(tree,decomposition);std::vector<longlong>result(static_cast<std::size_t>(size));result[0]=size;for(intdistance=1;distance<size;distance++){conststd::uint64_tordered=distance_frequency_detail::combine_residues(first[std::size_t(distance)].val(),second[std::size_t(distance)].val());assert((ordered&1)==0);result[std::size_t(distance)]=static_cast<longlong>(ordered/2);}returnresult;}}// namespace tree}// namespace m1une#line 1 "graph/tree/dsu_on_tree.hpp"
#line 7 "graph/tree/dsu_on_tree.hpp"
#line 9 "graph/tree/dsu_on_tree.hpp"
namespacem1une{namespacetree{template<classT=int>structDsuOnTree{intn;introot;std::vector<int>parent;std::vector<int>parent_edge;std::vector<int>depth;std::vector<int>subtree_size;std::vector<int>heavy_child;std::vector<int>tin;std::vector<int>tout;std::vector<int>order;std::vector<std::vector<int>>children;DsuOnTree():n(0),root(-1){}explicitDsuOnTree(constm1une::graph::Graph<T>&graph,introot_vertex=0){build(graph,root_vertex);}voidbuild(constm1une::graph::Graph<T>&graph,introot_vertex=0){n=graph.size();root=n==0?-1:root_vertex;parent.assign(n,-2);parent_edge.assign(n,-1);depth.assign(n,0);subtree_size.assign(n,1);heavy_child.assign(n,-1);tin.assign(n,-1);tout.assign(n,-1);order.clear();order.reserve(n);children.assign(n,{});if(n==0)return;assert(0<=root&&root<n);std::vector<int>stack;stack.push_back(root);parent[root]=-1;while(!stack.empty()){intvertex=stack.back();stack.pop_back();tin[vertex]=int(order.size());order.push_back(vertex);for(constauto&edge:graph[vertex]){if(!edge.alive||parent[edge.to]!=-2)continue;parent[edge.to]=vertex;parent_edge[edge.to]=edge.id;depth[edge.to]=depth[vertex]+1;children[vertex].push_back(edge.to);stack.push_back(edge.to);}}assert(int(order.size())==n);for(intindex=n-1;index>=0;--index){intvertex=order[index];for(intchild:children[vertex]){subtree_size[vertex]+=subtree_size[child];if(heavy_child[vertex]==-1||subtree_size[heavy_child[vertex]]<subtree_size[child]){heavy_child[vertex]=child;}}tout[vertex]=tin[vertex]+subtree_size[vertex];}}intsize()const{returnn;}boolempty()const{returnn==0;}std::pair<int,int>subtree_range(intvertex)const{assert(0<=vertex&&vertex<n);return{tin[vertex],tout[vertex]};}// Runs DSU on tree. `add(v)` inserts one vertex into the maintained state,// `remove(v)` erases it, and `answer(v)` observes the state for subtree(v).template<classAdd,classRemove,classAnswer>voidrun(Addadd,Removeremove,Answeranswer)const{if(n==0)return;enumActionType{Process,AddSubtree,AddVertex,AnswerVertex,RemoveSubtree,};structAction{ActionTypetype;intvertex;boolkeep;};std::vector<Action>actions;actions.reserve(3*std::size_t(n));actions.push_back(Action{Process,root,true});while(!actions.empty()){Actionaction=actions.back();actions.pop_back();intvertex=action.vertex;if(action.type==AddSubtree){for(intindex=tin[vertex];index<tout[vertex];++index){add(order[index]);}}elseif(action.type==AddVertex){add(vertex);}elseif(action.type==AnswerVertex){answer(vertex);}elseif(action.type==RemoveSubtree){for(intindex=tin[vertex];index<tout[vertex];++index){remove(order[index]);}}else{if(!action.keep){actions.push_back(Action{RemoveSubtree,vertex,false,});}actions.push_back(Action{AnswerVertex,vertex,false});actions.push_back(Action{AddVertex,vertex,false});for(intchild:children[vertex]){if(child!=heavy_child[vertex]){actions.push_back(Action{AddSubtree,child,false,});}}if(heavy_child[vertex]!=-1){actions.push_back(Action{Process,heavy_child[vertex],true,});}for(intchild:children[vertex]){if(child!=heavy_child[vertex]){actions.push_back(Action{Process,child,false});}}}}}};}// namespace tree}// namespace m1une#line 1 "graph/tree/euler_tour.hpp"
#line 8 "graph/tree/euler_tour.hpp"
#line 10 "graph/tree/euler_tour.hpp"
namespacem1une{namespacetree{template<classT=int>structEulerTour{usingcost_type=T;usingedge_type=m1une::graph::Edge<T>;introot;std::vector<int>parent;std::vector<int>parent_edge;std::vector<int>depth;std::vector<T>dist;std::vector<int>subtree_size;std::vector<int>tin;std::vector<int>tout;std::vector<int>order;std::vector<std::vector<int>>children;private:int_n;voidcheck_vertex(intv)const{assert(0<=v&&v<_n);assert(tin[v]!=-1);}public:EulerTour():root(-1),_n(0){}explicitEulerTour(constm1une::graph::Graph<T>&g,introot_=0){build(g,root_);}voidbuild(constm1une::graph::Graph<T>&g,introot_=0){_n=g.size();root=_n==0?-1:root_;parent.assign(_n,-2);parent_edge.assign(_n,-1);depth.assign(_n,0);dist.assign(_n,T(0));subtree_size.assign(_n,0);tin.assign(_n,-1);tout.assign(_n,-1);order.clear();order.reserve(_n);children.assign(_n,{});if(_n==0)return;assert(0<=root&&root<_n);structFrame{intv;intstate;};std::vector<Frame>stack;stack.push_back({root,0});parent[root]=-1;while(!stack.empty()){Frameframe=stack.back();stack.pop_back();intv=frame.v;if(frame.state==0){tin[v]=int(order.size());order.push_back(v);stack.push_back({v,1});constauto&adj=g[v];for(inti=int(adj.size())-1;i>=0;--i){constauto&e=adj[i];if(!e.alive)continue;if(parent[e.to]!=-2)continue;parent[e.to]=v;parent_edge[e.to]=e.id;depth[e.to]=depth[v]+1;dist[e.to]=dist[v]+e.cost;children[v].push_back(e.to);stack.push_back({e.to,0});}std::reverse(children[v].begin(),children[v].end());}else{subtree_size[v]=1;for(intchild:children[v])subtree_size[v]+=subtree_size[child];tout[v]=int(order.size());}}}intsize()const{return_n;}intvisited_size()const{returnint(order.size());}boolempty()const{return_n==0;}boolis_ancestor(intu,intv)const{check_vertex(u);check_vertex(v);returntin[u]<=tin[v]&&tout[v]<=tout[u];}boolin_subtree(intv,intu)const{returnis_ancestor(u,v);}std::pair<int,int>subtree_range(intv,booledge=false)const{check_vertex(v);return{tin[v]+(edge?1:0),tout[v]};}std::vector<int>subtree_vertices(intv)const{check_vertex(v);returnstd::vector<int>(order.begin()+tin[v],order.begin()+tout[v]);}template<classF>voidfor_each_subtree(intv,Ff)const{auto[l,r]=subtree_range(v);for(inti=l;i<r;++i)f(order[i]);}};}// namespace tree}// namespace m1une#line 1 "graph/tree/heavy_light_decomposition.hpp"
#line 8 "graph/tree/heavy_light_decomposition.hpp"
#line 10 "graph/tree/heavy_light_decomposition.hpp"
namespacem1une{namespacetree{structHldPathSegment{intl;intr;boolreversed;};template<classT=int>structHeavyLightDecomposition{usingcost_type=T;usingedge_type=m1une::graph::Edge<T>;introot;std::vector<int>parent;std::vector<int>parent_edge;std::vector<int>depth;std::vector<T>dist;std::vector<int>subtree_size;std::vector<int>heavy;std::vector<int>head;std::vector<int>tin;std::vector<int>tout;std::vector<int>order;private:int_n;voidcheck_vertex(intv)const{assert(0<=v&&v<_n);assert(tin[v]!=-1);}staticvoidadd_segment(std::vector<HldPathSegment>&result,intl,intr,boolreversed){if(l<r)result.push_back({l,r,reversed});}public:HeavyLightDecomposition():root(-1),_n(0){}explicitHeavyLightDecomposition(constm1une::graph::Graph<T>&g,introot_=0){build(g,root_);}voidbuild(constm1une::graph::Graph<T>&g,introot_=0){_n=g.size();root=_n==0?-1:root_;parent.assign(_n,-2);parent_edge.assign(_n,-1);depth.assign(_n,0);dist.assign(_n,T(0));subtree_size.assign(_n,1);heavy.assign(_n,-1);head.assign(_n,-1);tin.assign(_n,-1);tout.assign(_n,-1);order.clear();order.reserve(_n);if(_n==0)return;assert(0<=root&&root<_n);std::vector<int>dfs_order;dfs_order.reserve(_n);std::vector<int>stack={root};parent[root]=-1;while(!stack.empty()){intv=stack.back();stack.pop_back();dfs_order.push_back(v);for(constauto&e:g[v]){if(!e.alive)continue;if(parent[e.to]!=-2)continue;parent[e.to]=v;parent_edge[e.to]=e.id;depth[e.to]=depth[v]+1;dist[e.to]=dist[v]+e.cost;stack.push_back(e.to);}}for(inti=int(dfs_order.size())-1;i>=0;i--){intv=dfs_order[i];if(parent[v]==-1)continue;intp=parent[v];subtree_size[p]+=subtree_size[v];if(heavy[p]==-1||subtree_size[heavy[p]]<subtree_size[v])heavy[p]=v;}order.assign(dfs_order.size(),-1);inttimer=0;std::vector<std::pair<int,int>>starts={std::pair<int,int>{root,root}};while(!starts.empty()){auto[start,h]=starts.back();starts.pop_back();for(intv=start;v!=-1;v=heavy[v]){head[v]=h;tin[v]=timer;order[timer++]=v;for(autoit=g[v].rbegin();it!=g[v].rend();++it){if(!it->alive)continue;intto=it->to;if(parent[to]!=v||to==heavy[v])continue;starts.push_back({to,to});}}}for(inti=int(dfs_order.size())-1;i>=0;i--){intv=dfs_order[i];tout[v]=tin[v]+subtree_size[v];}}intsize()const{return_n;}boolempty()const{return_n==0;}boolis_ancestor(intu,intv)const{check_vertex(u);check_vertex(v);returntin[u]<=tin[v]&&tout[v]<=tout[u];}intlca(intu,intv)const{check_vertex(u);check_vertex(v);while(head[u]!=head[v]){if(depth[head[u]]<depth[head[v]])std::swap(u,v);u=parent[head[u]];}returndepth[u]<depth[v]?u:v;}intdist_edges(intu,intv)const{intw=lca(u,v);returndepth[u]+depth[v]-2*depth[w];}Tdist_cost(intu,intv)const{intw=lca(u,v);returndist[u]+dist[v]-dist[w]-dist[w];}intkth_ancestor(intv,intk)const{check_vertex(v);assert(0<=k);while(v!=-1){inth=head[v];intlen=depth[v]-depth[h];if(k<=len)returnorder[tin[v]-k];k-=len+1;v=parent[h];}return-1;}intjump(intfrom,intto,intk)const{check_vertex(from);check_vertex(to);assert(0<=k);intw=lca(from,to);intup_len=depth[from]-depth[w];intdown_len=depth[to]-depth[w];if(up_len+down_len<k)return-1;if(k<=up_len)returnkth_ancestor(from,k);returnkth_ancestor(to,down_len-(k-up_len));}std::pair<int,int>subtree_range(intv,booledge=false)const{check_vertex(v);return{tin[v]+(edge?1:0),tout[v]};}std::vector<HldPathSegment>path_segments(intu,intv,booledge=false)const{check_vertex(u);check_vertex(v);std::vector<HldPathSegment>result,down;while(head[u]!=head[v]){if(depth[head[u]]>=depth[head[v]]){add_segment(result,tin[head[u]],tin[u]+1,true);u=parent[head[u]];}else{add_segment(down,tin[head[v]],tin[v]+1,false);v=parent[head[v]];}}if(depth[u]>=depth[v]){add_segment(result,tin[v]+(edge?1:0),tin[u]+1,true);}else{add_segment(down,tin[u]+(edge?1:0),tin[v]+1,false);}std::reverse(down.begin(),down.end());result.insert(result.end(),down.begin(),down.end());returnresult;}template<classF>voidfor_each_path(intu,intv,Ff,booledge=false)const{for(autoseg:path_segments(u,v,edge))f(seg.l,seg.r,seg.reversed);}};}// namespace tree}// namespace m1une#line 1 "graph/tree/mo_on_tree.hpp"
#line 7 "graph/tree/mo_on_tree.hpp"
#line 1 "algo/offline/mo.hpp"
#line 7 "algo/offline/mo.hpp"
#include<numeric>
#line 9 "algo/offline/mo.hpp"
namespacem1une{namespacealgo{// Offline Mo's algorithm for half-open array ranges.structMo{structQuery{intleft;intright;intid;};private:int_n;std::vector<Query>_queries;public:Mo():_n(0){}explicitMo(intn):_n(n){assert(0<=n);}intsize()const{return_n;}intquery_count()const{returnint(_queries.size());}boolempty()const{return_queries.empty();}conststd::vector<Query>&queries()const{return_queries;}voidreserve(intquery_capacity){assert(0<=query_capacity);_queries.reserve(query_capacity);}voidclear(){_queries.clear();}// Adds [left, right) and returns its insertion-order ID.intadd_query(intleft,intright){assert(0<=left&&left<=right&&right<=_n);intid=query_count();_queries.push_back(Query{left,right,id});returnid;}// Returns query IDs in Mo order. A non-positive block size selects one// automatically.std::vector<int>order(intblock_size=0)const{intquery_size=query_count();std::vector<int>result(query_size);std::iota(result.begin(),result.end(),0);if(query_size==0)returnresult;if(block_size<=0){block_size=std::max(1,int(_n/std::sqrt(static_cast<double>(query_size))));}std::sort(result.begin(),result.end(),[&](intfirst,intsecond){constQuery&a=_queries[first];constQuery&b=_queries[second];intfirst_block=a.left/block_size;intsecond_block=b.left/block_size;if(first_block!=second_block){returnfirst_block<second_block;}if(first_block&1)returna.right>b.right;returna.right<b.right;});returnresult;}// Maintains [left, right). Each movement callback receives the array index// being inserted or erased. `answer(query_id)` stores or reports a result.template<classAddLeft,classAddRight,classRemoveLeft,classRemoveRight,classAnswer>voidrun(AddLeftadd_left,AddRightadd_right,RemoveLeftremove_left,RemoveRightremove_right,Answeranswer,intblock_size=0)const{intleft=0;intright=0;for(intquery_index:order(block_size)){constQuery&query=_queries[query_index];while(query.left<left)add_left(--left);while(right<query.right)add_right(right++);while(left<query.left)remove_left(left++);while(query.right<right)remove_right(--right);answer(query.id);}}// Convenience overload for statistics whose update is independent of// which side moves.template<classAdd,classRemove,classAnswer>voidrun(Addadd,Removeremove,Answeranswer,intblock_size=0)const{run(add,add,remove,remove,answer,block_size);}};}// namespace algo}// namespace m1une#line 11 "graph/tree/mo_on_tree.hpp"
namespacem1une{namespacetree{// Offline Mo's algorithm for static paths in a tree.template<classT=int>structMoOnTree{structQuery{intfrom;intto;intleft;intright;intextra;intid;booledge;};introot;std::vector<int>entry;std::vector<int>exit;std::vector<int>tour;private:int_n;HeavyLightDecomposition<T>_hld;m1une::algo::Mo_mo;std::vector<Query>_queries;voidcheck_vertex(intvertex)const{assert(0<=vertex&&vertex<_n);assert(entry[vertex]!=-1);}intadd_path_query(intfrom,intto,booledge){check_vertex(from);check_vertex(to);assert(_queries.empty()||_queries.front().edge==edge);intoriginal_from=from;intoriginal_to=to;if(entry[from]>entry[to])std::swap(from,to);intancestor=_hld.lca(from,to);intleft;intright=entry[to]+1;intextra=-1;if(ancestor==from){left=entry[from]+int(edge);}else{left=exit[from];if(!edge)extra=ancestor;}intid=_mo.add_query(left,right);_queries.push_back(Query{original_from,original_to,left,right,extra,id,edge,});returnid;}public:MoOnTree():root(-1),_n(0),_mo(0){}explicitMoOnTree(constm1une::graph::Graph<T>&graph,introot_vertex=0):root(-1),_n(0),_mo(0){build(graph,root_vertex);}voidbuild(constm1une::graph::Graph<T>&graph,introot_vertex=0){_n=graph.size();root=_n==0?-1:root_vertex;entry.assign(_n,-1);exit.assign(_n,-1);tour.clear();tour.reserve(2*_n);_queries.clear();_mo=m1une::algo::Mo(2*_n);_hld.build(graph,root_vertex);if(_n==0)return;assert(0<=root&&root<_n);for(intvertex=0;vertex<_n;++vertex){assert(_hld.parent[vertex]!=-2);}std::vector<std::vector<int>>children(_n);for(intvertex=0;vertex<_n;++vertex){intparent=_hld.parent[vertex];if(parent!=-1)children[parent].push_back(vertex);}structEvent{intvertex;boolleaving;};std::vector<Event>stack;stack.reserve(2*_n);stack.push_back(Event{root,false});while(!stack.empty()){Eventevent=stack.back();stack.pop_back();intvertex=event.vertex;if(event.leaving){exit[vertex]=int(tour.size());tour.push_back(vertex);continue;}entry[vertex]=int(tour.size());tour.push_back(vertex);stack.push_back(Event{vertex,true});constauto&child_list=children[vertex];for(intindex=int(child_list.size())-1;index>=0;--index){stack.push_back(Event{child_list[index],false});}}assert(int(tour.size())==2*_n);}intsize()const{return_n;}boolempty()const{return_n==0;}intquery_count()const{returnint(_queries.size());}conststd::vector<Query>&queries()const{return_queries;}intparent(intvertex)const{check_vertex(vertex);return_hld.parent[vertex];}intparent_edge(intvertex)const{check_vertex(vertex);return_hld.parent_edge[vertex];}intdepth(intvertex)const{check_vertex(vertex);return_hld.depth[vertex];}intlca(intfirst,intsecond)const{check_vertex(first);check_vertex(second);return_hld.lca(first,second);}voidreserve(intquery_capacity){assert(0<=query_capacity);_queries.reserve(query_capacity);_mo.reserve(query_capacity);}voidclear(){_queries.clear();_mo.clear();}// Adds an inclusive vertex-path query and returns its insertion-order ID.// Vertex and edge queries cannot be mixed in one collection.intadd_query(intfrom,intto){returnadd_path_query(from,to,false);}// Adds an edge-path query. Each edge is represented by its child vertex.intadd_edge_query(intfrom,intto){returnadd_path_query(from,to,true);}std::vector<int>order(intblock_size=0)const{return_mo.order(block_size);}// `add(v)` and `remove(v)` maintain the current path. In edge mode, v// always represents the real edge parent_edge(v).template<classAdd,classRemove,classAnswer>voidrun(Addadd,Removeremove,Answeranswer,intblock_size=0)const{booledge_mode=!_queries.empty()&&_queries.front().edge;std::vector<char>active(_n,false);autotoggle=[&](inttour_index){intvertex=tour[tour_index];if(!edge_mode||vertex!=root){if(active[vertex]){remove(vertex);}else{add(vertex);}}active[vertex]=!active[vertex];};_mo.run(toggle,toggle,[&](intquery_id){intextra=_queries[query_id].extra;if(extra!=-1){assert(!active[extra]);add(extra);}answer(query_id);if(extra!=-1)remove(extra);},block_size);}};}// namespace tree}// namespace m1une#line 1 "graph/tree/range_contour_query.hpp"
#line 7 "graph/tree/range_contour_query.hpp"
#line 1 "graph/tree/rooted_tree.hpp"
#line 7 "graph/tree/rooted_tree.hpp"
#line 9 "graph/tree/rooted_tree.hpp"
namespacem1une{namespacetree{template<classT=int>structRootedTree{usingcost_type=T;usingedge_type=m1une::graph::Edge<T>;introot;std::vector<int>parent;std::vector<int>parent_edge;std::vector<int>depth;std::vector<T>dist;std::vector<int>subtree_size;std::vector<int>tin;std::vector<int>tout;std::vector<int>order;std::vector<std::vector<int>>up;private:int_n;int_log;voidcheck_vertex(intv)const{assert(0<=v&&v<_n);assert(tin[v]!=-1);}public:RootedTree():root(-1),_n(0),_log(0){}explicitRootedTree(constm1une::graph::Graph<T>&g,introot_=0){build(g,root_);}voidbuild(constm1une::graph::Graph<T>&g,introot_=0){_n=g.size();root=_n==0?-1:root_;_log=1;while((1U<<_log)<=(unsignedint)(std::max(1,_n)))_log++;parent.assign(_n,-1);parent_edge.assign(_n,-1);depth.assign(_n,0);dist.assign(_n,T(0));subtree_size.assign(_n,0);tin.assign(_n,-1);tout.assign(_n,-1);order.clear();order.reserve(_n);up.assign(_log,std::vector<int>(_n,-1));if(_n==0)return;assert(0<=root&&root<_n);structFrame{intv;intstate;};std::vector<char>visited(_n,false);std::vector<Frame>stack;stack.push_back({root,0});visited[root]=true;inttimer=0;while(!stack.empty()){Frameframe=stack.back();stack.pop_back();intv=frame.v;if(frame.state==0){tin[v]=timer++;order.push_back(v);up[0][v]=parent[v];for(intk=1;k<_log;k++){intp=up[k-1][v];up[k][v]=p==-1?-1:up[k-1][p];}stack.push_back({v,1});constauto&adj=g[v];for(inti=int(adj.size())-1;i>=0;i--){constauto&e=adj[i];if(!e.alive)continue;if(visited[e.to])continue;visited[e.to]=true;parent[e.to]=v;parent_edge[e.to]=e.id;depth[e.to]=depth[v]+1;dist[e.to]=dist[v]+e.cost;stack.push_back({e.to,0});}}else{subtree_size[v]++;if(parent[v]!=-1)subtree_size[parent[v]]+=subtree_size[v];tout[v]=timer;}}}intsize()const{return_n;}boolempty()const{return_n==0;}intlog()const{return_log;}boolis_ancestor(intu,intv)const{check_vertex(u);check_vertex(v);returntin[u]<=tin[v]&&tout[v]<=tout[u];}boolin_subtree(intv,intu)const{returnis_ancestor(u,v);}intkth_ancestor(intv,intk)const{check_vertex(v);assert(0<=k);intbit=0;while(k>0&&v!=-1){if(k&1){if(_log<=bit)return-1;v=up[bit][v];}k>>=1;bit++;}returnv;}intlca(intu,intv)const{check_vertex(u);check_vertex(v);if(depth[u]<depth[v])std::swap(u,v);u=kth_ancestor(u,depth[u]-depth[v]);if(u==v)returnu;for(intk=_log-1;k>=0;k--){if(up[k][u]!=up[k][v]){u=up[k][u];v=up[k][v];}}returnparent[u];}intdist_edges(intu,intv)const{intw=lca(u,v);returndepth[u]+depth[v]-2*depth[w];}Tdist_cost(intu,intv)const{intw=lca(u,v);returndist[u]+dist[v]-dist[w]-dist[w];}intjump(intfrom,intto,intk)const{check_vertex(from);check_vertex(to);assert(0<=k);intw=lca(from,to);intup_len=depth[from]-depth[w];intdown_len=depth[to]-depth[w];if(up_len+down_len<k)return-1;if(k<=up_len)returnkth_ancestor(from,k);returnkth_ancestor(to,down_len-(k-up_len));}std::vector<int>path(intu,intv)const{check_vertex(u);check_vertex(v);intw=lca(u,v);std::vector<int>a,b;for(intx=u;x!=w;x=parent[x])a.push_back(x);a.push_back(w);for(intx=v;x!=w;x=parent[x])b.push_back(x);std::reverse(b.begin(),b.end());a.insert(a.end(),b.begin(),b.end());returna;}std::vector<int>path_edges(intu,intv)const{check_vertex(u);check_vertex(v);intw=lca(u,v);std::vector<int>a,b;for(intx=u;x!=w;x=parent[x])a.push_back(parent_edge[x]);for(intx=v;x!=w;x=parent[x])b.push_back(parent_edge[x]);std::reverse(b.begin(),b.end());a.insert(a.end(),b.begin(),b.end());returna;}std::pair<int,int>subtree_range(intv)const{check_vertex(v);return{tin[v],tout[v]};}std::vector<int>subtree_vertices(intv)const{check_vertex(v);returnstd::vector<int>(order.begin()+tin[v],order.begin()+tout[v]);}};}// namespace tree}// namespace m1une#line 13 "graph/tree/range_contour_query.hpp"
namespacem1une{namespacetree{namespaceinternal{structRangeContourPathEntry{intcentroid;intdistance;intsubtree;};structRangeContourLayout{intn=0;std::vector<std::vector<RangeContourPathEntry>>path;std::vector<int>all_size;std::vector<int>subtree_size;template<classEdgeCost>voidbuild(constm1une::graph::Graph<EdgeCost>&graph){n=graph.size();path.assign(n,{});all_size.assign(n,0);subtree_size.assign(n,0);if(n==0)return;#ifndef NDEBUG
std::vector<int>incidence(graph.edge_count(),0);for(intvertex=0;vertex<n;vertex++){for(constauto&edge:graph[vertex]){if(!edge.alive)continue;assert(0<=edge.id&&edge.id<graph.edge_count());incidence[edge.id]++;}}intactive_edges=0;for(intcount:incidence){if(count==0)continue;assert(count==2);active_edges++;}assert(active_edges==n-1);#endif
RootedTree<EdgeCost>rooted(graph,0);assert(int(rooted.order.size())==n);CentroidDecomposition<EdgeCost>decomposition(graph);for(intvertex=0;vertex<n;vertex++){intprevious=-1;for(intcentroid=vertex;centroid!=-1;centroid=decomposition.parent[centroid]){intdistance=rooted.dist_edges(vertex,centroid);path[vertex].push_back(RangeContourPathEntry{centroid,distance,previous});all_size[centroid]=std::max(all_size[centroid],distance+1);if(previous!=-1){subtree_size[previous]=std::max(subtree_size[previous],distance+1);}previous=centroid;}}}};template<m1une::monoid::IsCommutativeGroupGroup>classRangeContourFenwick{public:usingT=typenameGroup::value_type;private:int_n=0;std::vector<T>_data;Tprefix_product(intright)const{Tresult=Group::id();while(right>0){result=Group::op(result,_data[right]);right-=right&-right;}returnresult;}public:RangeContourFenwick():_data(1,Group::id()){}explicitRangeContourFenwick(intn):_n(n),_data(n+1,Group::id()){assert(0<=n);}intsize()const{return_n;}voidapply(intindex,constT&value){assert(0<=index&&index<_n);for(index++;index<=_n;index+=index&-index){_data[index]=Group::op(_data[index],value);}}Tproduct(intleft,intright)const{left=std::max(left,0);right=std::min(right,_n);if(right<=left)returnGroup::id();returnGroup::op(Group::inv(prefix_product(left)),prefix_product(right));}voidrange_apply(intleft,intright,constT&value){left=std::max(left,0);right=std::min(right,_n);if(right<=left)return;apply(left,value);if(right<_n)apply(right,Group::inv(value));}Tget(intindex)const{assert(0<=index&&index<_n);returnprefix_product(index+1);}};}// namespace internaltemplate<m1une::monoid::IsCommutativeGroupGroup>classVertexApplyRangeContourProduct{public:usingT=typenameGroup::value_type;private:internal::RangeContourLayout_layout;std::vector<T>_value;std::vector<internal::RangeContourFenwick<Group>>_all;std::vector<internal::RangeContourFenwick<Group>>_subtree;voidcheck_vertex(intvertex)const{assert(0<=vertex&&vertex<size());}public:VertexApplyRangeContourProduct()=default;template<classEdgeCost>explicitVertexApplyRangeContourProduct(constm1une::graph::Graph<EdgeCost>&graph,conststd::vector<T>&initial={}){build(graph,initial);}template<classEdgeCost>voidbuild(constm1une::graph::Graph<EdgeCost>&graph,conststd::vector<T>&initial={}){assert(initial.empty()||int(initial.size())==graph.size());_layout.build(graph);constintn=_layout.n;_value.assign(n,Group::id());_all.assign(n,internal::RangeContourFenwick<Group>());_subtree.assign(n,internal::RangeContourFenwick<Group>());for(intindex=0;index<n;index++){_all[index]=internal::RangeContourFenwick<Group>(_layout.all_size[index]);_subtree[index]=internal::RangeContourFenwick<Group>(_layout.subtree_size[index]);}if(!initial.empty()){for(intvertex=0;vertex<n;vertex++){apply(vertex,initial[vertex]);}}}intsize()const{return_layout.n;}boolempty()const{returnsize()==0;}Tget(intvertex)const{check_vertex(vertex);return_value[vertex];}voidapply(intvertex,constT&value){check_vertex(vertex);_value[vertex]=Group::op(_value[vertex],value);for(constauto&entry:_layout.path[vertex]){_all[entry.centroid].apply(entry.distance,value);if(entry.subtree!=-1){_subtree[entry.subtree].apply(entry.distance,value);}}}voidset(intvertex,constT&value){check_vertex(vertex);apply(vertex,Group::op(Group::inv(_value[vertex]),value));}Tprod(intvertex,intleft_distance,intright_distance)const{check_vertex(vertex);assert(0<=left_distance&&left_distance<=right_distance);Tresult=Group::id();for(constauto&entry:_layout.path[vertex]){intleft=left_distance-entry.distance;intright=right_distance-entry.distance;result=Group::op(result,_all[entry.centroid].product(left,right));if(entry.subtree!=-1){result=Group::op(result,Group::inv(_subtree[entry.subtree].product(left,right)));}}returnresult;}};template<m1une::monoid::IsCommutativeGroupGroup>classVertexGetRangeContourApply{public:usingT=typenameGroup::value_type;private:internal::RangeContourLayout_layout;std::vector<T>_base;std::vector<internal::RangeContourFenwick<Group>>_all;std::vector<internal::RangeContourFenwick<Group>>_subtree;voidcheck_vertex(intvertex)const{assert(0<=vertex&&vertex<size());}public:VertexGetRangeContourApply()=default;template<classEdgeCost>explicitVertexGetRangeContourApply(constm1une::graph::Graph<EdgeCost>&graph,conststd::vector<T>&initial={}){build(graph,initial);}template<classEdgeCost>voidbuild(constm1une::graph::Graph<EdgeCost>&graph,conststd::vector<T>&initial={}){assert(initial.empty()||int(initial.size())==graph.size());_layout.build(graph);constintn=_layout.n;_base=initial.empty()?std::vector<T>(n,Group::id()):initial;_all.assign(n,internal::RangeContourFenwick<Group>());_subtree.assign(n,internal::RangeContourFenwick<Group>());for(intindex=0;index<n;index++){_all[index]=internal::RangeContourFenwick<Group>(_layout.all_size[index]);_subtree[index]=internal::RangeContourFenwick<Group>(_layout.subtree_size[index]);}}intsize()const{return_layout.n;}boolempty()const{returnsize()==0;}Tget(intvertex)const{check_vertex(vertex);Tresult=_base[vertex];for(constauto&entry:_layout.path[vertex]){result=Group::op(result,_all[entry.centroid].get(entry.distance));if(entry.subtree!=-1){result=Group::op(result,Group::inv(_subtree[entry.subtree].get(entry.distance)));}}returnresult;}voidpoint_apply(intvertex,constT&value){check_vertex(vertex);_base[vertex]=Group::op(_base[vertex],value);}voidset(intvertex,constT&value){check_vertex(vertex);_base[vertex]=Group::op(_base[vertex],Group::op(Group::inv(get(vertex)),value));}voidapply(intvertex,intleft_distance,intright_distance,constT&value){check_vertex(vertex);assert(0<=left_distance&&left_distance<=right_distance);for(constauto&entry:_layout.path[vertex]){intleft=left_distance-entry.distance;intright=right_distance-entry.distance;_all[entry.centroid].range_apply(left,right,value);if(entry.subtree!=-1){_subtree[entry.subtree].range_apply(left,right,value);}}}};template<classT>classVertexAddRangeContourSum:publicVertexApplyRangeContourProduct<m1une::monoid::Add<T>>{private:usingBase=VertexApplyRangeContourProduct<m1une::monoid::Add<T>>;public:usingBase::Base;voidadd(intvertex,constT&delta){Base::apply(vertex,delta);}Tsum(intvertex,intleft_distance,intright_distance)const{returnBase::prod(vertex,left_distance,right_distance);}};template<classT>classVertexGetRangeContourAdd:publicVertexGetRangeContourApply<m1une::monoid::Add<T>>{private:usingBase=VertexGetRangeContourApply<m1une::monoid::Add<T>>;public:usingBase::Base;voidadd(intvertex,constT&delta){Base::point_apply(vertex,delta);}};}// namespace tree}// namespace m1une#line 1 "graph/tree/rerooting_dp.hpp"
#line 5 "graph/tree/rerooting_dp.hpp"
#line 7 "graph/tree/rerooting_dp.hpp"
namespacem1une{namespacetree{template<classT,classDP,classMerge,classAddVertex,classAddEdge>std::vector<DP>rerooting_dp(constm1une::graph::Graph<T>&g,DPid,Mergemerge,AddVertexadd_vertex,AddEdgeadd_edge){intn=g.size();std::vector<int>parent(n,-2),parent_edge(n,-1),order;order.reserve(n);for(introot=0;root<n;root++){if(parent[root]!=-2)continue;parent[root]=-1;std::vector<int>stack={root};while(!stack.empty()){intv=stack.back();stack.pop_back();order.push_back(v);for(constauto&e:g[v]){if(!e.alive)continue;if(parent[e.to]!=-2)continue;parent[e.to]=v;parent_edge[e.to]=e.id;stack.push_back(e.to);}}}std::vector<DP>down(n,id),outside(n,id),answer(n,id);for(inti=n-1;i>=0;i--){intv=order[i];DPacc=id;for(constauto&e:g[v]){if(!e.alive)continue;if(parent[e.to]!=v)continue;acc=merge(acc,add_edge(down[e.to],e));}down[v]=add_vertex(acc,v);}for(intv:order){intd=int(g[v].size());std::vector<DP>contrib(d,id);for(inti=0;i<d;i++){constauto&e=g[v][i];if(!e.alive)continue;if(parent[e.to]==v){contrib[i]=add_edge(down[e.to],e);}elseif(parent[v]==e.to&&parent_edge[v]==e.id){contrib[i]=add_edge(outside[v],e);}}std::vector<DP>pref(d+1,id),suff(d+1,id);for(inti=0;i<d;i++)pref[i+1]=merge(pref[i],contrib[i]);for(inti=d-1;i>=0;i--)suff[i]=merge(contrib[i],suff[i+1]);answer[v]=add_vertex(pref[d],v);for(inti=0;i<d;i++){constauto&e=g[v][i];if(!e.alive)continue;if(parent[e.to]!=v)continue;outside[e.to]=add_vertex(merge(pref[i],suff[i+1]),v);}}returnanswer;}}// namespace tree}// namespace m1une#line 1 "graph/tree/rerooting_static_top_tree.hpp"
#line 10 "graph/tree/rerooting_static_top_tree.hpp"
#line 12 "graph/tree/rerooting_static_top_tree.hpp"
namespacem1une{namespacetree{namespaceinternal{enumclassRerootingStaticTopTreeNodeType{Compress,Rake,AddEdge,AddVertex,};enumclassRerootingStaticTopTreeStepType{CompressLower,CompressUpper,AddEdge,RakeLeft,RakeRight,AddVertex,};}// namespace internaltemplate<classT,classVertex,classPath,classPoint,classCompressDown,classCompressUp,classRake,classAddEdgeDown,classAddEdgeUp,classAddVertex>structRerootingStaticTopTree{usingcost_type=T;usingvertex_type=Vertex;usingpath_type=Path;usingpoint_type=Point;usingedge_type=m1une::graph::Edge<T>;usingnode_type=internal::RerootingStaticTopTreeNodeType;usingstep_type=internal::RerootingStaticTopTreeStepType;structNode{node_typetype;intleft=-1;intright=-1;intparent=-1;intvertex=-1;edge_typeedge;intsize=0;intheight=1;std::optional<Path>path_down;std::optional<Path>path_up;std::optional<Point>point;};structRerootingStep{step_typetype;intnode=-1;intsibling=-1;intvertex=-1;edge_typeedge;};private:int_n;int_root;int_root_node;Point_point_id;CompressDown_compress_down;CompressUp_compress_up;Rake_rake;AddEdgeDown_add_edge_down;AddEdgeUp_add_edge_up;AddVertex_add_vertex;std::vector<Vertex>_values;std::vector<Node>_nodes;std::vector<int>_vertex_node;std::vector<int>_edge_node;std::vector<int>_parent;std::vector<int>_subtree_size;std::vector<int>_heavy;std::vector<edge_type>_heavy_edge;std::vector<std::vector<edge_type>>_children;staticedge_typereversed_edge(edge_typee){std::swap(e.from,e.to);returne;}constPath&node_path_down(intnode)const{assert(0<=node&&node<int(_nodes.size()));assert(_nodes[node].path_down.has_value());return*_nodes[node].path_down;}constPath&node_path_up(intnode)const{assert(0<=node&&node<int(_nodes.size()));assert(_nodes[node].path_up.has_value());return*_nodes[node].path_up;}constPoint&node_point(intnode)const{assert(0<=node&&node<int(_nodes.size()));assert(_nodes[node].point.has_value());return*_nodes[node].point;}voidset_parent(intchild,intparent){if(child!=-1)_nodes[child].parent=parent;}voidrecompute(intnode){auto&x=_nodes[node];if(x.type==node_type::Compress){x.path_down=_compress_down(node_path_down(x.left),node_path_down(x.right),x.edge);x.path_up=_compress_up(node_path_up(x.right),node_path_up(x.left),reversed_edge(x.edge));}elseif(x.type==node_type::Rake){x.point=_rake(node_point(x.left),node_point(x.right));}elseif(x.type==node_type::AddEdge){x.point=_add_edge_down(node_path_down(x.left),x.edge);}else{constPoint&side=x.left==-1?_point_id:node_point(x.left);Pathpath=_add_vertex(side,_values[x.vertex],x.vertex);x.path_down=path;x.path_up=std::move(path);}}intnew_node(Nodenode){intid=int(_nodes.size());_nodes.push_back(std::move(node));set_parent(_nodes[id].left,id);set_parent(_nodes[id].right,id);recompute(id);returnid;}intnew_compress(intleft,intright,edge_typeedge){Nodenode;node.type=node_type::Compress;node.left=left;node.right=right;node.edge=edge;node.size=_nodes[left].size+_nodes[right].size;node.height=std::max(_nodes[left].height,_nodes[right].height)+1;intid=new_node(std::move(node));if(0<=edge.id&&edge.id<int(_edge_node.size()))_edge_node[edge.id]=id;returnid;}intnew_rake(intleft,intright){Nodenode;node.type=node_type::Rake;node.left=left;node.right=right;node.size=_nodes[left].size+_nodes[right].size;node.height=std::max(_nodes[left].height,_nodes[right].height)+1;returnnew_node(std::move(node));}intnew_add_edge(intchild,edge_typeedge){Nodenode;node.type=node_type::AddEdge;node.left=child;node.edge=edge;node.size=_nodes[child].size;node.height=_nodes[child].height+1;intid=new_node(std::move(node));if(0<=edge.id&&edge.id<int(_edge_node.size()))_edge_node[edge.id]=id;returnid;}intnew_add_vertex(intside,intvertex){Nodenode;node.type=node_type::AddVertex;node.left=side;node.vertex=vertex;node.size=1+(side==-1?0:_nodes[side].size);node.height=1+(side==-1?0:_nodes[side].height);intid=new_node(std::move(node));_vertex_node[vertex]=id;returnid;}intweighted_split(conststd::vector<int>&nodes,intl,intr)const{inttotal=0;for(inti=l;i<r;i++)total+=_nodes[nodes[i]].size;intleft_sum=0;for(inti=l;i+1<r;i++){left_sum+=_nodes[nodes[i]].size;if(2*left_sum>=total)returni+1;}returnr-1;}intbuild_rake(conststd::vector<int>&nodes,intl,intr){if(l==r)return-1;if(l+1==r)returnnodes[l];intm=weighted_split(nodes,l,r);returnnew_rake(build_rake(nodes,l,m),build_rake(nodes,m,r));}intbuild_compress(conststd::vector<int>&nodes,conststd::vector<edge_type>&edges,intl,intr){if(l+1==r)returnnodes[l];intm=weighted_split(nodes,l,r);returnnew_compress(build_compress(nodes,edges,l,m),build_compress(nodes,edges,m,r),edges[m-1]);}intbuild_vertex(intv){std::vector<int>side_nodes;for(constauto&e:_children[v]){if(e.to==_heavy[v])continue;intchild_path=build_path(e.to);side_nodes.push_back(new_add_edge(child_path,e));}returnnew_add_vertex(build_rake(side_nodes,0,int(side_nodes.size())),v);}intbuild_path(intstart){std::vector<int>path_nodes;std::vector<edge_type>path_edges;for(intv=start;v!=-1;v=_heavy[v]){path_nodes.push_back(build_vertex(v));if(_heavy[v]!=-1)path_edges.push_back(_heavy_edge[v]);}returnbuild_compress(path_nodes,path_edges,0,int(path_nodes.size()));}voidrecompute_up(intnode){while(node!=-1){recompute(node);node=_nodes[node].parent;}}public:RerootingStaticTopTree(constm1une::graph::Graph<T>&g,conststd::vector<Vertex>&values,Pointpoint_id,CompressDowncompress_down,CompressUpcompress_up,Rakerake,AddEdgeDownadd_edge_down,AddEdgeUpadd_edge_up,AddVertexadd_vertex,introot=0):_n(g.size()),_root(_n==0?-1:root),_root_node(-1),_point_id(std::move(point_id)),_compress_down(std::move(compress_down)),_compress_up(std::move(compress_up)),_rake(std::move(rake)),_add_edge_down(std::move(add_edge_down)),_add_edge_up(std::move(add_edge_up)),_add_vertex(std::move(add_vertex)),_values(values){build(g,root);}voidbuild(constm1une::graph::Graph<T>&g,introot=0){_n=g.size();_root=_n==0?-1:root;assert(int(_values.size())==_n);_nodes.clear();_vertex_node.assign(_n,-1);_edge_node.assign(g.edge_count(),-1);_parent.assign(_n,-2);_subtree_size.assign(_n,1);_heavy.assign(_n,-1);_heavy_edge.assign(_n,edge_type());_children.assign(_n,{});_root_node=-1;if(_n==0)return;assert(0<=root&&root<_n);assert(int(g.edges().size())==_n-1);std::vector<int>order;order.reserve(_n);std::vector<int>stack={root};_parent[root]=-1;while(!stack.empty()){intv=stack.back();stack.pop_back();order.push_back(v);for(constauto&e:g[v]){if(!e.alive)continue;if(_parent[e.to]!=-2)continue;_parent[e.to]=v;_children[v].push_back(e);stack.push_back(e.to);}}assert(int(order.size())==_n);for(inti=int(order.size())-1;i>=0;i--){intv=order[i];for(constauto&e:_children[v]){_subtree_size[v]+=_subtree_size[e.to];if(_heavy[v]==-1||_subtree_size[_heavy[v]]<_subtree_size[e.to]){_heavy[v]=e.to;_heavy_edge[v]=e;}}}_root_node=build_path(root);}intsize()const{return_n;}boolempty()const{return_n==0;}introot()const{return_root;}introot_node()const{return_root_node;}intnode_count()const{returnint(_nodes.size());}intheight()const{return_root_node==-1?0:_nodes[_root_node].height;}conststd::vector<Node>&nodes()const{return_nodes;}constNode&node(intid)const{assert(0<=id&&id<int(_nodes.size()));return_nodes[id];}intparent_node(intid)const{returnnode(id).parent;}intvertex_node(intv)const{assert(0<=v&&v<_n);return_vertex_node[v];}intlocal_point_node(intv)const{intid=vertex_node(v);assert(_nodes[id].type==node_type::AddVertex);return_nodes[id].left;}constPoint&local_point(intv)const{intpoint_node=local_point_node(v);returnpoint_node==-1?_point_id:node_point(point_node);}constVertex&get(intv)const{assert(0<=v&&v<_n);return_values[v];}constVertex&operator[](intv)const{returnget(v);}voidset(intv,constVertex&value){assert(0<=v&&v<_n);assert(_vertex_node[v]!=-1);_values[v]=value;recompute_up(_vertex_node[v]);}voidset(intv,Vertex&&value){assert(0<=v&&v<_n);assert(_vertex_node[v]!=-1);_values[v]=std::move(value);recompute_up(_vertex_node[v]);}voidset_edge_cost(intedge_id,Tcost){assert(0<=edge_id&&edge_id<int(_edge_node.size()));intnode=_edge_node[edge_id];assert(node!=-1);_nodes[node].edge.cost=cost;recompute_up(node);}constPath&path_down(intnode_id)const{returnnode_path_down(node_id);}constPath&path_up(intnode_id)const{returnnode_path_up(node_id);}constPoint&point(intnode_id)const{returnnode_point(node_id);}constPath&all_prod_down()const{assert(_root_node!=-1);returnpath_down(_root_node);}constPath&all_prod_up()const{assert(_root_node!=-1);returnpath_up(_root_node);}constPoint&point_id()const{return_point_id;}template<classF>voidfor_each_rerooting_step(intv,F&&f)const{assert(0<=v&&v<_n);intcur=_vertex_node[v];assert(cur!=-1);while(_nodes[cur].parent!=-1){intpar=_nodes[cur].parent;constauto&p=_nodes[par];RerootingStepstep;step.node=par;if(p.type==node_type::Compress){step.edge=p.edge;if(p.left==cur){step.type=step_type::CompressLower;step.sibling=p.right;}else{assert(p.right==cur);step.type=step_type::CompressUpper;step.sibling=p.left;}}elseif(p.type==node_type::Rake){if(p.left==cur){step.type=step_type::RakeRight;step.sibling=p.right;}else{assert(p.right==cur);step.type=step_type::RakeLeft;step.sibling=p.left;}}elseif(p.type==node_type::AddEdge){assert(p.left==cur);step.type=step_type::AddEdge;step.edge=p.edge;}else{assert(p.type==node_type::AddVertex);assert(p.left==cur);step.type=step_type::AddVertex;step.vertex=p.vertex;}f(step);cur=par;}}std::vector<RerootingStep>rerooting_steps(intv)const{std::vector<RerootingStep>result;intcur=vertex_node(v);intdepth=0;while(_nodes[cur].parent!=-1){cur=_nodes[cur].parent;depth++;}result.reserve(depth);for_each_rerooting_step(v,[&](constRerootingStep&step){result.push_back(step);});returnresult;}template<classFolder>autofold_rerooting(intv,Folderfolder)const{folder.start(v,_values[v],local_point(v));for_each_rerooting_step(v,[&](constRerootingStep&step){if(step.type==step_type::CompressLower){folder.compress_lower(path_down(step.sibling),step.edge);}elseif(step.type==step_type::CompressUpper){folder.compress_upper(path_up(step.sibling),reversed_edge(step.edge));}elseif(step.type==step_type::AddEdge){folder.add_edge(reversed_edge(step.edge));}elseif(step.type==step_type::RakeLeft){folder.rake_left(point(step.sibling));}elseif(step.type==step_type::RakeRight){folder.rake_right(point(step.sibling));}else{folder.add_vertex(step.vertex,_values[step.vertex]);}});returnfolder.result();}Pathcompress_down(constPath&upper,constPath&lower,edge_typeedge)const{return_compress_down(upper,lower,edge);}Pathcompress_up(constPath&lower,constPath&upper,edge_typeedge)const{return_compress_up(lower,upper,edge);}Pointrake(constPoint&left,constPoint&right)const{return_rake(left,right);}Pointadd_edge_down(constPath&path,edge_typeedge)const{return_add_edge_down(path,edge);}Pointadd_edge_up(constPath&path,edge_typeedge)const{return_add_edge_up(path,edge);}Pathadd_vertex(constPoint&side,constVertex&value,intvertex)const{return_add_vertex(side,value,vertex);}staticedge_typereverse_edge(edge_typeedge){returnreversed_edge(edge);}};template<classT,classVertex,classPoint,classCompressDown,classCompressUp,classRake,classAddEdgeDown,classAddEdgeUp,classAddVertex>RerootingStaticTopTree(constm1une::graph::Graph<T>&,conststd::vector<Vertex>&,Point,CompressDown,CompressUp,Rake,AddEdgeDown,AddEdgeUp,AddVertex,int)->RerootingStaticTopTree<T,Vertex,std::invoke_result_t<AddVertex,Point,Vertex,int>,Point,CompressDown,CompressUp,Rake,AddEdgeDown,AddEdgeUp,AddVertex>;template<classT,classVertex,classPoint,classCompressDown,classCompressUp,classRake,classAddEdgeDown,classAddEdgeUp,classAddVertex>RerootingStaticTopTree(constm1une::graph::Graph<T>&,conststd::vector<Vertex>&,Point,CompressDown,CompressUp,Rake,AddEdgeDown,AddEdgeUp,AddVertex)->RerootingStaticTopTree<T,Vertex,std::invoke_result_t<AddVertex,Point,Vertex,int>,Point,CompressDown,CompressUp,Rake,AddEdgeDown,AddEdgeUp,AddVertex>;}// namespace tree}// namespace m1une#line 1 "graph/tree/sparse_table_lca.hpp"
#line 9 "graph/tree/sparse_table_lca.hpp"
#line 1 "ds/range_query/sparse_table.hpp"
#line 9 "ds/range_query/sparse_table.hpp"
#line 11 "ds/range_query/sparse_table.hpp"
namespacem1une{namespaceds{// A Sparse Table utilizing C++20 Concepts for type safety.// It requires a Monoid struct that satisfies `m1une::monoid::IsMonoid`.// [IMPORTANT] For O(1) range queries to work correctly, the monoid operation MUST be idempotent.// i.e., Monoid::op(x, x) == x must hold (e.g., Min, Max, GCD, Bitwise AND/OR).template<m1une::monoid::IsMonoidMonoid>structSparseTable{usingT=typenameMonoid::value_type;private:int_n;std::vector<std::vector<T>>_st;public:// Constructs an empty sparse table.SparseTable():_n(0){}// Constructs a sparse table from an existing vector in O(N log N) time.explicitSparseTable(conststd::vector<T>&v):_n(int(v.size())){if(_n==0)return;// Compute the maximum power of 2 neededintmax_log=std::bit_width((unsignedint)_n);_st.assign(max_log,std::vector<T>(_n));// Initialize the base levelfor(inti=0;i<_n;i++){_st[0][i]=v[i];}// Build the sparse tablefor(intk=1;k<max_log;k++){for(inti=0;i+(1<<k)<=_n;i++){_st[k][i]=Monoid::op(_st[k-1][i],_st[k-1][i+(1<<(k-1))]);}}}explicitSparseTable(std::vector<T>&&v):_n(int(v.size())){if(_n==0)return;intmax_log=std::bit_width((unsignedint)_n);_st.assign(max_log,std::vector<T>(_n));for(inti=0;i<_n;i++){_st[0][i]=std::move(v[i]);}for(intk=1;k<max_log;k++){for(inti=0;i+(1<<k)<=_n;i++){_st[k][i]=Monoid::op(_st[k-1][i],_st[k-1][i+(1<<(k-1))]);}}}// Constructs a sparse table from a vector of a different type U.// It automatically adapts to the Monoid's initialization requirements:// 1. Monoid::make(val) if it exists.// 2. Monoid::make(val, index) if the monoid requires global indices.// 3. static_cast<T>(val) as a fallback for simple monoids.template<typenameU>requires(!std::same_as<U,T>)&&(requires(Ux){Monoid::make(x);}||requires(Ux,inti){Monoid::make(x,i);}||std::convertible_to<U,T>)explicitSparseTable(conststd::vector<U>&v):_n(int(v.size())){if(_n==0)return;intmax_log=std::bit_width((unsignedint)_n);_st.assign(max_log,std::vector<T>(_n));// Compile-time branching based on the available make() signaturefor(inti=0;i<_n;i++){ifconstexpr(requires(Ux){Monoid::make(x);}){_st[0][i]=Monoid::make(v[i]);}elseifconstexpr(requires(Ux,intidx){Monoid::make(x,idx);}){_st[0][i]=Monoid::make(v[i],i);}else{_st[0][i]=static_cast<T>(v[i]);}}for(intk=1;k<max_log;k++){for(inti=0;i+(1<<k)<=_n;i++){_st[k][i]=Monoid::op(_st[k-1][i],_st[k-1][i+(1<<(k-1))]);}}}// Returns the product (result of the monoid operation) in the range [l, r) in O(1) time.// Requires the monoid operation to be idempotent.Tprod(intl,intr)const{assert(0<=l&&l<=r&&r<=_n);if(l==r)returnMonoid::id();// Calculate the largest power of 2 less than or equal to the interval lengthintk=std::bit_width((unsignedint)(r-l))-1;returnMonoid::op(_st[k][l],_st[k][r-(1<<k)]);}};}// namespace ds}// namespace m1une#line 12 "graph/tree/sparse_table_lca.hpp"
namespacem1une{namespacetree{template<classT=int>structSparseTableLca{usingcost_type=T;usingedge_type=m1une::graph::Edge<T>;introot;std::vector<int>parent;std::vector<int>parent_edge;std::vector<int>depth;std::vector<T>dist;std::vector<int>subtree_size;std::vector<int>tin;std::vector<int>tout;std::vector<int>order;std::vector<int>first;std::vector<int>euler;private:structRmqNode{intdepth;intvertex;};structRmqMonoid{usingvalue_type=RmqNode;staticvalue_typeid(){return{std::numeric_limits<int>::max(),-1};}staticvalue_typeop(constvalue_type&a,constvalue_type&b){if(a.depth!=b.depth)returna.depth<b.depth?a:b;returna.vertex<b.vertex?a:b;}};int_n;m1une::ds::SparseTable<RmqMonoid>_st;voidcheck_vertex(intv)const{assert(0<=v&&v<_n);assert(first[v]!=-1);}public:SparseTableLca():root(-1),_n(0){}explicitSparseTableLca(constm1une::graph::Graph<T>&g,introot_=0){build(g,root_);}voidbuild(constm1une::graph::Graph<T>&g,introot_=0){_n=g.size();root=_n==0?-1:root_;parent.assign(_n,-2);parent_edge.assign(_n,-1);depth.assign(_n,0);dist.assign(_n,T(0));subtree_size.assign(_n,0);tin.assign(_n,-1);tout.assign(_n,-1);order.clear();order.reserve(_n);first.assign(_n,-1);euler.clear();euler.reserve(std::max(0,2*_n-1));_st=m1une::ds::SparseTable<RmqMonoid>();if(_n==0)return;assert(0<=root&&root<_n);std::vector<int>it(_n,0);std::vector<char>visited(_n,false);std::vector<int>stack={root};visited[root]=true;parent[root]=-1;inttimer=0;tin[root]=timer++;order.push_back(root);first[root]=0;euler.push_back(root);while(!stack.empty()){intv=stack.back();if(it[v]<int(g[v].size())){constauto&e=g[v][it[v]++];if(!e.alive)continue;if(visited[e.to])continue;visited[e.to]=true;parent[e.to]=v;parent_edge[e.to]=e.id;depth[e.to]=depth[v]+1;dist[e.to]=dist[v]+e.cost;tin[e.to]=timer++;order.push_back(e.to);first[e.to]=int(euler.size());euler.push_back(e.to);stack.push_back(e.to);}else{subtree_size[v]++;if(parent[v]!=-1)subtree_size[parent[v]]+=subtree_size[v];tout[v]=timer;stack.pop_back();if(!stack.empty())euler.push_back(stack.back());}}std::vector<RmqNode>rmq;rmq.reserve(euler.size());for(intv:euler)rmq.push_back({depth[v],v});_st=m1une::ds::SparseTable<RmqMonoid>(std::move(rmq));}intsize()const{return_n;}boolempty()const{return_n==0;}boolis_ancestor(intu,intv)const{check_vertex(u);check_vertex(v);returntin[u]<=tin[v]&&tout[v]<=tout[u];}boolin_subtree(intv,intu)const{returnis_ancestor(u,v);}intlca(intu,intv)const{check_vertex(u);check_vertex(v);intl=first[u],r=first[v];if(l>r)std::swap(l,r);return_st.prod(l,r+1).vertex;}intdist_edges(intu,intv)const{intw=lca(u,v);returndepth[u]+depth[v]-2*depth[w];}Tdist_cost(intu,intv)const{intw=lca(u,v);returndist[u]+dist[v]-dist[w]-dist[w];}std::pair<int,int>subtree_range(intv)const{check_vertex(v);return{tin[v],tout[v]};}};}// namespace tree}// namespace m1une#line 1 "graph/tree/static_top_tree.hpp"
#line 10 "graph/tree/static_top_tree.hpp"
#line 12 "graph/tree/static_top_tree.hpp"
namespacem1une{namespacetree{namespaceinternal{enumclassStaticTopTreeNodeType{Compress,Rake,AddEdge,AddVertex,};}// namespace internaltemplate<classT,classVertex,classPath,classPoint,classCompress,classRake,classAddEdge,classAddVertex>structStaticTopTree{usingcost_type=T;usingvertex_type=Vertex;usingpath_type=Path;usingpoint_type=Point;usingedge_type=m1une::graph::Edge<T>;private:structNode{internal::StaticTopTreeNodeTypetype;intleft=-1;intright=-1;intparent=-1;intvertex=-1;edge_typeedge;intsize=0;intheight=1;std::optional<Path>path;std::optional<Point>point;};int_n;int_root;int_root_node;Point_point_id;Compress_compress;Rake_rake;AddEdge_add_edge;AddVertex_add_vertex;std::vector<Vertex>_values;std::vector<Node>_nodes;std::vector<int>_vertex_node;std::vector<int>_edge_node;std::vector<int>_parent;std::vector<int>_subtree_size;std::vector<int>_heavy;std::vector<edge_type>_heavy_edge;std::vector<std::vector<edge_type>>_children;constPath&path_value(intnode)const{assert(0<=node&&node<int(_nodes.size()));assert(_nodes[node].path.has_value());return*_nodes[node].path;}constPoint&point_value(intnode)const{assert(0<=node&&node<int(_nodes.size()));assert(_nodes[node].point.has_value());return*_nodes[node].point;}voidset_parent(intchild,intparent){if(child!=-1)_nodes[child].parent=parent;}voidrecompute(intnode){auto&x=_nodes[node];if(x.type==internal::StaticTopTreeNodeType::Compress){x.path=_compress(path_value(x.left),path_value(x.right),x.edge);}elseif(x.type==internal::StaticTopTreeNodeType::Rake){x.point=_rake(point_value(x.left),point_value(x.right));}elseif(x.type==internal::StaticTopTreeNodeType::AddEdge){x.point=_add_edge(path_value(x.left),x.edge);}else{constPoint&side=x.left==-1?_point_id:point_value(x.left);x.path=_add_vertex(side,_values[x.vertex],x.vertex);}}intnew_node(Nodenode){intid=int(_nodes.size());_nodes.push_back(std::move(node));set_parent(_nodes[id].left,id);set_parent(_nodes[id].right,id);recompute(id);returnid;}intnew_compress(intleft,intright,edge_typeedge){Nodenode;node.type=internal::StaticTopTreeNodeType::Compress;node.left=left;node.right=right;node.edge=edge;node.size=_nodes[left].size+_nodes[right].size;node.height=std::max(_nodes[left].height,_nodes[right].height)+1;intid=new_node(std::move(node));if(0<=edge.id&&edge.id<int(_edge_node.size()))_edge_node[edge.id]=id;returnid;}intnew_rake(intleft,intright){Nodenode;node.type=internal::StaticTopTreeNodeType::Rake;node.left=left;node.right=right;node.size=_nodes[left].size+_nodes[right].size;node.height=std::max(_nodes[left].height,_nodes[right].height)+1;returnnew_node(std::move(node));}intnew_add_edge(intchild,edge_typeedge){Nodenode;node.type=internal::StaticTopTreeNodeType::AddEdge;node.left=child;node.edge=edge;node.size=_nodes[child].size;node.height=_nodes[child].height+1;intid=new_node(std::move(node));if(0<=edge.id&&edge.id<int(_edge_node.size()))_edge_node[edge.id]=id;returnid;}intnew_add_vertex(intside,intvertex){Nodenode;node.type=internal::StaticTopTreeNodeType::AddVertex;node.left=side;node.vertex=vertex;node.size=1+(side==-1?0:_nodes[side].size);node.height=1+(side==-1?0:_nodes[side].height);intid=new_node(std::move(node));_vertex_node[vertex]=id;returnid;}intweighted_split(conststd::vector<int>&nodes,intl,intr)const{inttotal=0;for(inti=l;i<r;i++)total+=_nodes[nodes[i]].size;intleft_sum=0;for(inti=l;i+1<r;i++){left_sum+=_nodes[nodes[i]].size;if(2*left_sum>=total)returni+1;}returnr-1;}intbuild_rake(conststd::vector<int>&nodes,intl,intr){if(l==r)return-1;if(l+1==r)returnnodes[l];intm=weighted_split(nodes,l,r);returnnew_rake(build_rake(nodes,l,m),build_rake(nodes,m,r));}intbuild_compress(conststd::vector<int>&nodes,conststd::vector<edge_type>&edges,intl,intr){if(l+1==r)returnnodes[l];intm=weighted_split(nodes,l,r);returnnew_compress(build_compress(nodes,edges,l,m),build_compress(nodes,edges,m,r),edges[m-1]);}intbuild_vertex(intv){std::vector<int>side_nodes;for(constauto&e:_children[v]){if(e.to==_heavy[v])continue;intchild_path=build_path(e.to);side_nodes.push_back(new_add_edge(child_path,e));}returnnew_add_vertex(build_rake(side_nodes,0,int(side_nodes.size())),v);}intbuild_path(intstart){std::vector<int>path_nodes;std::vector<edge_type>path_edges;for(intv=start;v!=-1;v=_heavy[v]){path_nodes.push_back(build_vertex(v));if(_heavy[v]!=-1)path_edges.push_back(_heavy_edge[v]);}returnbuild_compress(path_nodes,path_edges,0,int(path_nodes.size()));}voidrecompute_up(intnode){while(node!=-1){recompute(node);node=_nodes[node].parent;}}public:StaticTopTree(constm1une::graph::Graph<T>&g,conststd::vector<Vertex>&values,Pointpoint_id,Compresscompress,Rakerake,AddEdgeadd_edge,AddVertexadd_vertex,introot=0):_n(g.size()),_root(_n==0?-1:root),_root_node(-1),_point_id(std::move(point_id)),_compress(std::move(compress)),_rake(std::move(rake)),_add_edge(std::move(add_edge)),_add_vertex(std::move(add_vertex)),_values(values){build(g,root);}voidbuild(constm1une::graph::Graph<T>&g,introot=0){_n=g.size();_root=_n==0?-1:root;assert(int(_values.size())==_n);_nodes.clear();_vertex_node.assign(_n,-1);_edge_node.assign(g.edge_count(),-1);_parent.assign(_n,-2);_subtree_size.assign(_n,1);_heavy.assign(_n,-1);_heavy_edge.assign(_n,edge_type());_children.assign(_n,{});_root_node=-1;if(_n==0)return;assert(0<=root&&root<_n);assert(int(g.edges().size())==_n-1);std::vector<int>order;order.reserve(_n);std::vector<int>stack={root};_parent[root]=-1;while(!stack.empty()){intv=stack.back();stack.pop_back();order.push_back(v);for(constauto&e:g[v]){if(!e.alive)continue;if(_parent[e.to]!=-2)continue;_parent[e.to]=v;_children[v].push_back(e);stack.push_back(e.to);}}assert(int(order.size())==_n);for(inti=int(order.size())-1;i>=0;i--){intv=order[i];for(constauto&e:_children[v]){_subtree_size[v]+=_subtree_size[e.to];if(_heavy[v]==-1||_subtree_size[_heavy[v]]<_subtree_size[e.to]){_heavy[v]=e.to;_heavy_edge[v]=e;}}}_root_node=build_path(root);}intsize()const{return_n;}boolempty()const{return_n==0;}introot()const{return_root;}intnode_count()const{returnint(_nodes.size());}intheight()const{return_root_node==-1?0:_nodes[_root_node].height;}constVertex&get(intv)const{assert(0<=v&&v<_n);return_values[v];}constVertex&operator[](intv)const{returnget(v);}voidset(intv,constVertex&value){assert(0<=v&&v<_n);assert(_vertex_node[v]!=-1);_values[v]=value;recompute_up(_vertex_node[v]);}voidset(intv,Vertex&&value){assert(0<=v&&v<_n);assert(_vertex_node[v]!=-1);_values[v]=std::move(value);recompute_up(_vertex_node[v]);}voidset_edge_cost(intedge_id,Tcost){assert(0<=edge_id&&edge_id<int(_edge_node.size()));intnode=_edge_node[edge_id];assert(node!=-1);_nodes[node].edge.cost=cost;recompute_up(node);}constPath&all_prod()const{assert(_root_node!=-1);returnpath_value(_root_node);}constPath&query()const{returnall_prod();}};template<classT,classVertex,classPoint,classCompress,classRake,classAddEdge,classAddVertex>StaticTopTree(constm1une::graph::Graph<T>&,conststd::vector<Vertex>&,Point,Compress,Rake,AddEdge,AddVertex,int)->StaticTopTree<T,Vertex,std::invoke_result_t<AddVertex,Point,Vertex,int>,Point,Compress,Rake,AddEdge,AddVertex>;template<classT,classVertex,classPoint,classCompress,classRake,classAddEdge,classAddVertex>StaticTopTree(constm1une::graph::Graph<T>&,conststd::vector<Vertex>&,Point,Compress,Rake,AddEdge,AddVertex)->StaticTopTree<T,Vertex,std::invoke_result_t<AddVertex,Point,Vertex,int>,Point,Compress,Rake,AddEdge,AddVertex>;}// namespace tree}// namespace m1une#line 1 "graph/tree/tree.hpp"
#line 9 "graph/tree/tree.hpp"
#line 1 "graph/tree/tree_hash.hpp"
#line 9 "graph/tree/tree_hash.hpp"
#line 11 "graph/tree/tree_hash.hpp"
namespacem1une{namespacetree{usingTreeHashValue=std::array<std::uint64_t,2>;classTreeHasher{private:staticconstexprstd::uint64_tmod=(std::uint64_t(1)<<61)-1;std::uint64_t_seed;staticstd::uint64_tsplitmix64(std::uint64_tx){x+=0x9e3779b97f4a7c15ULL;x=(x^(x>>30))*0xbf58476d1ce4e5b9ULL;x=(x^(x>>27))*0x94d049bb133111ebULL;returnx^(x>>31);}staticstd::uint64_tmul_mod(std::uint64_ta,std::uint64_tb){__uint128_tproduct=static_cast<__uint128_t>(a)*b;std::uint64_tresult=std::uint64_t(product&mod)+std::uint64_t(product>>61);if(mod<=result)result-=mod;returnresult;}staticstd::uint64_tadd_mod(std::uint64_ta,std::uint64_tb){std::uint64_tresult=a+b;if(mod<=result)result-=mod;returnresult;}TreeHashValuesalt(intheight)const{std::uint64_tx=static_cast<std::uint64_t>(height);std::uint64_tfirst=splitmix64(_seed^(x+0x243f6a8885a308d3ULL));std::uint64_tsecond=splitmix64(_seed^(x+0x13198a2e03707344ULL));return{first%(mod-1)+1,second%(mod-1)+1};}template<classT>staticstd::vector<int>tree_centers(constm1une::graph::Graph<T>&g){intn=g.size();if(n==0)return{};std::vector<int>degree(n,0);std::vector<int>queue;queue.reserve(n);longlongactive_arcs=0;for(intv=0;v<n;v++){for(constauto&e:g[v]){if(!e.alive)continue;degree[v]++;active_arcs++;}if(degree[v]<=1)queue.push_back(v);}assert(active_arcs==2LL*(n-1));std::vector<char>removed(n,false);intremaining=n;inthead=0;while(2<remaining){intlayer_end=int(queue.size());assert(head<layer_end);remaining-=layer_end-head;while(head<layer_end){intv=queue[head++];removed[v]=true;for(constauto&e:g[v]){if(!e.alive||removed[e.to])continue;if(--degree[e.to]==1)queue.push_back(e.to);}}}std::vector<int>centers;for(intv=0;v<n;v++){if(!removed[v])centers.push_back(v);}assert(1<=int(centers.size())&&int(centers.size())<=2);returncenters;}public:explicitTreeHasher(std::uint64_tseed=0x6a09e667f3bcc909ULL):_seed(seed){}std::uint64_tseed()const{return_seed;}template<classT>std::vector<TreeHashValue>hash_subtrees(constm1une::graph::Graph<T>&g,introot=0)const{intn=g.size();if(n==0)return{};assert(0<=root&&root<n);std::vector<int>parent(n,-1);std::vector<int>order;order.reserve(n);parent[root]=root;order.push_back(root);longlongactive_arcs=0;for(intv=0;v<n;v++){for(constauto&e:g[v])active_arcs+=e.alive;}assert(active_arcs==2LL*(n-1));for(inti=0;i<int(order.size());i++){intv=order[i];for(constauto&e:g[v]){if(!e.alive||parent[e.to]!=-1)continue;parent[e.to]=v;order.push_back(e.to);}}assert(int(order.size())==n);std::vector<int>height(n,0);std::vector<TreeHashValue>result(n,TreeHashValue{1,1});for(inti=n-1;i>=0;i--){intv=order[i];for(constauto&e:g[v]){if(!e.alive||parent[e.to]!=v)continue;height[v]=std::max(height[v],height[e.to]+1);}TreeHashValuerandom=salt(height[v]);for(constauto&e:g[v]){if(!e.alive||parent[e.to]!=v)continue;result[v][0]=mul_mod(result[v][0],add_mod(result[e.to][0],random[0]));result[v][1]=mul_mod(result[v][1],add_mod(result[e.to][1],random[1]));}}returnresult;}template<classT>TreeHashValuehash_rooted(constm1une::graph::Graph<T>&g,introot=0)const{if(g.empty())return{0,0};returnhash_subtrees(g,root)[root];}template<classT>std::vector<TreeHashValue>hash_unrooted(constm1une::graph::Graph<T>&g)const{std::vector<int>centers=tree_centers(g);std::vector<TreeHashValue>result;result.reserve(centers.size());for(intcenter:centers)result.push_back(hash_rooted(g,center));std::sort(result.begin(),result.end());returnresult;}};}// namespace tree}// namespace m1une#line 1 "graph/tree/virtual_tree.hpp"
#line 8 "graph/tree/virtual_tree.hpp"
#line 11 "graph/tree/virtual_tree.hpp"
namespacem1une{namespacetree{template<classT=int>structVirtualTreeResult{std::vector<int>vertex;std::vector<int>parent;std::vector<int>parent_edge_count;std::vector<T>parent_cost;std::vector<std::vector<int>>children;std::vector<bool>is_key;intsize()const{returnint(vertex.size());}boolempty()const{returnvertex.empty();}intedge_count()const{returnvertex.empty()?0:int(vertex.size())-1;}introot()const{returnvertex.empty()?-1:0;}introot_vertex()const{returnvertex.empty()?-1:vertex[0];}};template<classT=int>structVirtualTree{usingcost_type=T;usingresult_type=VirtualTreeResult<T>;private:SparseTableLca<T>_lca;std::vector<int>_key;std::vector<int>_vertices;std::vector<int>_stack;public:VirtualTree()=default;explicitVirtualTree(constm1une::graph::Graph<T>&graph,introot=0):_lca(graph,root){}voidbuild_lca(constm1une::graph::Graph<T>&graph,introot=0){_lca.build(graph,root);}intoriginal_size()const{return_lca.size();}constSparseTableLca<T>&lca_data()const{return_lca;}result_typebuild(std::vector<int>key_vertices){result_typeresult;if(key_vertices.empty())returnresult;autoby_tin=[&](intu,intv){return_lca.tin[u]<_lca.tin[v];};for(intv:key_vertices){assert(0<=v&&v<_lca.size());assert(_lca.tin[v]!=-1);}std::sort(key_vertices.begin(),key_vertices.end(),by_tin);key_vertices.erase(std::unique(key_vertices.begin(),key_vertices.end()),key_vertices.end());_key=key_vertices;_vertices=key_vertices;_vertices.reserve(2*_key.size());for(inti=1;i<int(_key.size());i++){_vertices.push_back(_lca.lca(_key[i-1],_key[i]));}std::sort(_vertices.begin(),_vertices.end(),by_tin);_vertices.erase(std::unique(_vertices.begin(),_vertices.end()),_vertices.end());intn=int(_vertices.size());result.vertex=_vertices;result.parent.assign(n,-1);result.parent_edge_count.assign(n,0);result.parent_cost.assign(n,T(0));result.children.assign(n,{});result.is_key.assign(n,false);intkey_index=0;for(inti=0;i<n;i++){while(key_index<int(_key.size())&&_lca.tin[_key[key_index]]<_lca.tin[_vertices[i]]){key_index++;}if(key_index<int(_key.size())&&_key[key_index]==_vertices[i])result.is_key[i]=true;}_stack.clear();_stack.reserve(n);for(inti=0;i<n;i++){while(!_stack.empty()&&!_lca.is_ancestor(_vertices[_stack.back()],_vertices[i])){_stack.pop_back();}if(!_stack.empty()){intp=_stack.back();result.parent[i]=p;result.parent_edge_count[i]=_lca.depth[_vertices[i]]-_lca.depth[_vertices[p]];result.parent_cost[i]=_lca.dist[_vertices[i]]-_lca.dist[_vertices[p]];result.children[p].push_back(i);}_stack.push_back(i);}returnresult;}};}// namespace tree}// namespace m1une#line 1 "graph/tree/zero_one_on_tree.hpp"
#line 7 "graph/tree/zero_one_on_tree.hpp"
#line 9 "graph/tree/zero_one_on_tree.hpp"
namespacem1une{namespacetree{inlinelonglongzero_one_on_tree(conststd::vector<int>&parent,conststd::vector<int>&value){constintn=int(parent.size());assert(int(value.size())==n);if(n==0)return0;introot=-1;std::vector<std::vector<int>>children(n);for(intv=0;v<n;v++){assert(value[v]==0||value[v]==1);if(parent[v]==-1){assert(root==-1);root=v;}else{assert(0<=parent[v]&&parent[v]<n&&parent[v]!=v);children[parent[v]].push_back(v);}}assert(root!=-1);std::vector<int>stack(1,root);std::vector<char>visited(n,false);visited[root]=true;intvisited_count=0;while(!stack.empty()){constintv=stack.back();stack.pop_back();visited_count++;for(intchild:children[v]){assert(!visited[child]);visited[child]=true;stack.push_back(child);}}assert(visited_count==n);structComponent{longlongzeros;longlongones;intvertex;};structCompare{booloperator()(constComponent&lhs,constComponent&rhs)const{constlonglonglhs_product=lhs.zeros*rhs.ones;constlonglongrhs_product=rhs.zeros*lhs.ones;if(lhs_product!=rhs_product)returnlhs_product<rhs_product;returnlhs.vertex<rhs.vertex;}};std::vector<longlong>zeros(n),ones(n);std::vector<int>dsu(n);std::set<Component,Compare>components;for(intv=0;v<n;v++){zeros[v]=value[v]==0;ones[v]=value[v]==1;dsu[v]=v;if(v!=root)components.insert(Component{zeros[v],ones[v],v});}autoleader=[&](intv){intresult=v;while(dsu[result]!=result)result=dsu[result];while(dsu[v]!=v){constintnext=dsu[v];dsu[v]=result;v=next;}returnresult;};longlonganswer=0;while(!components.empty()){autoit=components.end();--it;constComponentchild=*it;components.erase(it);constintp=leader(parent[child.vertex]);if(p!=root){constinterased=int(components.erase(Component{zeros[p],ones[p],p}));assert(erased==1);}answer+=ones[p]*zeros[child.vertex];zeros[p]+=zeros[child.vertex];ones[p]+=ones[child.vertex];dsu[child.vertex]=p;if(p!=root)components.insert(Component{zeros[p],ones[p],p});}returnanswer;}template<classT>longlongzero_one_on_tree(constm1une::graph::Graph<T>&graph,conststd::vector<int>&value,introot=0){constintn=graph.size();assert(int(value.size())==n);if(n==0)return0;assert(0<=root&&root<n);assert(int(graph.edges().size())==n-1);RootedTree<T>rooted_tree(graph,root);assert(int(rooted_tree.order.size())==n);returnzero_one_on_tree(rooted_tree.parent,value);}}// namespace tree}// namespace m1une#line 23 "graph/tree/all.hpp"
#line 1 "graph/undirected.hpp"
#line 1 "graph/biconnected_components.hpp"
#line 6 "graph/biconnected_components.hpp"
#line 8 "graph/biconnected_components.hpp"
namespacem1une{namespacegraph{structBiconnectedComponentsResult{std::vector<std::vector<int>>components;std::vector<std::vector<int>>edge_components;std::vector<int>component_of_edge;std::vector<std::vector<int>>vertex_components;std::vector<int>articulation;std::vector<int>ord;std::vector<int>low;intcomponent_count()const{returnint(components.size());}boolis_articulation(intvertex)const{assert(0<=vertex&&vertex<int(vertex_components.size()));returnvertex_components[vertex].size()>=2;}};// Decomposes an undirected graph into maximal vertex-biconnected blocks.// Every active edge belongs to exactly one block. Isolated vertices form// singleton blocks, and articulation vertices occur in multiple blocks.template<classT>BiconnectedComponentsResultbiconnected_components(constGraph<T>&graph){constintn=graph.size();constintedge_count=graph.edge_count();BiconnectedComponentsResultresult;result.component_of_edge.assign(edge_count,-1);result.vertex_components.assign(n,{});result.ord.assign(n,-1);result.low.assign(n,-1);std::vector<int>edge_from(edge_count,-1);std::vector<int>edge_to(edge_count,-1);std::vector<int>incidence_count(edge_count,0);std::vector<int>alive_degree(n,0);for(intvertex=0;vertex<n;vertex++){for(constEdge<T>&edge:graph[vertex]){if(!edge.alive)continue;assert(0<=edge.id&&edge.id<edge_count);alive_degree[vertex]++;if(incidence_count[edge.id]==0){edge_from[edge.id]=edge.from;edge_to[edge.id]=edge.to;}incidence_count[edge.id]++;}}#ifndef NDEBUG
for(intedge_id=0;edge_id<edge_count;edge_id++){if(incidence_count[edge_id]==0)continue;assert(incidence_count[edge_id]==2);assert(edge_from[edge_id]!=edge_to[edge_id]);}#endif
std::vector<int>parent(n,-1);std::vector<int>parent_edge(n,-1);std::vector<int>next_edge(n,0);std::vector<int>dfs_stack;std::vector<int>edge_stack;std::vector<int>vertex_mark(n,-1);inttimer=0;autoadd_singleton=[&](intvertex){constintcomponent=result.component_count();result.components.push_back(std::vector<int>(1,vertex));result.edge_components.emplace_back();result.vertex_components[vertex].push_back(component);};autoextract_component=[&](intstopping_edge){constintcomponent=result.component_count();result.components.emplace_back();result.edge_components.emplace_back();std::vector<int>&vertices=result.components.back();std::vector<int>&edges=result.edge_components.back();while(true){assert(!edge_stack.empty());constintedge_id=edge_stack.back();edge_stack.pop_back();edges.push_back(edge_id);result.component_of_edge[edge_id]=component;constintendpoints[2]={edge_from[edge_id],edge_to[edge_id]};for(intvertex:endpoints){if(vertex_mark[vertex]==component)continue;vertex_mark[vertex]=component;vertices.push_back(vertex);}if(edge_id==stopping_edge)break;}for(intvertex:vertices){result.vertex_components[vertex].push_back(component);}};for(introot=0;root<n;root++){if(result.ord[root]!=-1)continue;if(alive_degree[root]==0){result.ord[root]=result.low[root]=timer++;add_singleton(root);continue;}result.ord[root]=result.low[root]=timer++;dfs_stack.push_back(root);while(!dfs_stack.empty()){constintvertex=dfs_stack.back();if(next_edge[vertex]<int(graph[vertex].size())){constEdge<T>&edge=graph[vertex][next_edge[vertex]++];if(!edge.alive||edge.id==parent_edge[vertex])continue;constintto=edge.to;if(result.ord[to]==-1){parent[to]=vertex;parent_edge[to]=edge.id;edge_stack.push_back(edge.id);result.ord[to]=result.low[to]=timer++;dfs_stack.push_back(to);}elseif(result.ord[to]<result.ord[vertex]){edge_stack.push_back(edge.id);if(result.ord[to]<result.low[vertex]){result.low[vertex]=result.ord[to];}}continue;}dfs_stack.pop_back();constintparent_vertex=parent[vertex];if(parent_vertex==-1){assert(edge_stack.empty());continue;}if(result.low[vertex]<result.low[parent_vertex]){result.low[parent_vertex]=result.low[vertex];}if(result.ord[parent_vertex]<=result.low[vertex]){extract_component(parent_edge[vertex]);}}}for(intvertex=0;vertex<n;vertex++){if(result.is_articulation(vertex))result.articulation.push_back(vertex);}returnresult;}}// namespace graph}// namespace m1une#line 1 "graph/block_cut_tree.hpp"
#line 6 "graph/block_cut_tree.hpp"
#line 8 "graph/block_cut_tree.hpp"
namespacem1une{namespacegraph{structBlockCutTreeResult{std::vector<std::vector<int>>forest;std::vector<int>node_of_block;std::vector<int>node_of_articulation;std::vector<int>node_of_vertex;std::vector<int>block_of_node;std::vector<int>articulation_of_node;intnode_count()const{returnint(forest.size());}intblock_count()const{returnint(node_of_block.size());}boolis_block_node(intnode)const{assert(0<=node&&node<node_count());returnblock_of_node[node]!=-1;}boolis_articulation_node(intnode)const{assert(0<=node&&node<node_count());returnarticulation_of_node[node]!=-1;}};// Builds the block-cut forest of a biconnected-components decomposition.// Block nodes have IDs [0, block_count); articulation nodes follow them.inlineBlockCutTreeResultblock_cut_tree(constBiconnectedComponentsResult&biconnected){constintvertex_count=int(biconnected.vertex_components.size());constintblock_count=biconnected.component_count();BlockCutTreeResultresult;result.node_of_block.resize(block_count);result.node_of_articulation.assign(vertex_count,-1);result.node_of_vertex.assign(vertex_count,-1);result.forest.resize(block_count);result.block_of_node.resize(block_count);result.articulation_of_node.assign(block_count,-1);for(intblock=0;block<block_count;block++){result.node_of_block[block]=block;result.block_of_node[block]=block;}for(intvertex=0;vertex<vertex_count;vertex++){conststd::vector<int>&blocks=biconnected.vertex_components[vertex];assert(!blocks.empty());if(blocks.size()==1){assert(0<=blocks[0]&&blocks[0]<block_count);result.node_of_vertex[vertex]=result.node_of_block[blocks[0]];continue;}constintnode=result.node_count();result.node_of_articulation[vertex]=node;result.node_of_vertex[vertex]=node;result.forest.emplace_back();result.block_of_node.push_back(-1);result.articulation_of_node.push_back(vertex);for(intblock:blocks){assert(0<=block&&block<block_count);constintblock_node=result.node_of_block[block];result.forest[node].push_back(block_node);result.forest[block_node].push_back(node);}}returnresult;}template<classT>BlockCutTreeResultblock_cut_tree(constGraph<T>&graph){returnblock_cut_tree(biconnected_components(graph));}}// namespace graph}// namespace m1une#line 1 "graph/chordal_graph_recognition.hpp"
#line 9 "graph/chordal_graph_recognition.hpp"
#line 11 "graph/chordal_graph_recognition.hpp"
namespacem1une{namespacegraph{structChordalGraphResult{boolis_chordal;std::vector<int>perfect_elimination_order;std::vector<int>induced_cycle;};namespaceinternal{classMaximumCardinalitySearch{std::vector<int>_head;std::vector<int>_next;std::vector<int>_previous;std::vector<int>_weight;voiderase(intvertex){constintweight=_weight[vertex];if(_previous[vertex]==-1){_head[weight]=_next[vertex];}else{_next[_previous[vertex]]=_next[vertex];}if(_next[vertex]!=-1)_previous[_next[vertex]]=_previous[vertex];}voidinsert(intvertex){constintweight=_weight[vertex];_previous[vertex]=-1;_next[vertex]=_head[weight];if(_head[weight]!=-1)_previous[_head[weight]]=vertex;_head[weight]=vertex;}public:explicitMaximumCardinalitySearch(intsize):_head(size+1,-1),_next(size,-1),_previous(size,-1),_weight(size,0){for(intvertex=0;vertex<size;vertex++)insert(vertex);}std::vector<int>run(conststd::vector<std::vector<int>>&adjacency){constintsize=int(adjacency.size());std::vector<int>order;order.reserve(size);std::vector<char>selected(size,false);std::vector<int>seen_neighbor(size,-1);intmaximum_weight=0;while(int(order.size())<size){while(_head[maximum_weight]==-1)maximum_weight--;constintvertex=_head[maximum_weight];erase(vertex);selected[vertex]=true;order.push_back(vertex);for(intto:adjacency[vertex]){if(to==vertex||selected[to]||seen_neighbor[to]==vertex)continue;seen_neighbor[to]=vertex;erase(to);_weight[to]++;insert(to);maximum_weight=std::max(maximum_weight,_weight[to]);}}returnorder;}};inlinestd::vector<int>chordless_cycle(conststd::vector<std::vector<int>>&adjacency,intvertex,intfirst,intsecond){constintsize=int(adjacency.size());std::vector<char>forbidden(size,false);for(intto:adjacency[vertex])forbidden[to]=true;forbidden[vertex]=true;forbidden[first]=false;forbidden[second]=false;std::vector<int>parent(size,-1);std::queue<int>queue;parent[first]=first;queue.push(first);while(!queue.empty()&&parent[second]==-1){constintcurrent=queue.front();queue.pop();for(intto:adjacency[current]){if(forbidden[to]||parent[to]!=-1)continue;parent[to]=current;queue.push(to);}}assert(parent[second]!=-1);std::vector<int>path;for(intcurrent=second;current!=first;current=parent[current]){path.push_back(current);}path.push_back(first);std::reverse(path.begin(),path.end());std::vector<int>cycle;cycle.reserve(path.size()+1);cycle.push_back(vertex);cycle.insert(cycle.end(),path.begin(),path.end());returncycle;}}// namespace internal// Recognizes a chordal graph. On success, returns a perfect elimination// ordering; on failure, returns an induced cycle of length at least four.template<classT>ChordalGraphResultchordal_graph_recognition(constGraph<T>&graph){constintsize=graph.size();std::vector<std::vector<int>>adjacency(size);for(constEdge<T>&edge:graph.edges()){if(edge.from==edge.to)continue;adjacency[edge.from].push_back(edge.to);adjacency[edge.to].push_back(edge.from);}std::vector<int>order=internal::MaximumCardinalitySearch(size).run(adjacency);std::vector<int>position(size);for(intindex=0;index<size;index++)position[order[index]]=index;std::vector<int>parent(size,-1);std::vector<std::vector<int>>children(size);for(intvertex=0;vertex<size;vertex++){for(intto:adjacency[vertex]){if(position[to]<position[vertex]&&(parent[vertex]==-1||position[parent[vertex]]<position[to])){parent[vertex]=to;}}if(parent[vertex]!=-1)children[parent[vertex]].push_back(vertex);}std::vector<int>adjacent_stamp(size,-1);for(intcenter=0;center<size;center++){for(intto:adjacency[center])adjacent_stamp[to]=center;for(intvertex:children[center]){for(intto:adjacency[vertex]){if(position[to]>=position[center]||adjacent_stamp[to]==center)continue;returnChordalGraphResult{false,{},internal::chordless_cycle(adjacency,vertex,to,center),};}}}std::reverse(order.begin(),order.end());returnChordalGraphResult{true,std::move(order),{}};}template<classT>boolis_chordal(constGraph<T>&graph){returnchordal_graph_recognition(graph).is_chordal;}}// namespace graph}// namespace m1une#line 1 "graph/chromatic_number.hpp"
#line 9 "graph/chromatic_number.hpp"
#line 11 "graph/chromatic_number.hpp"
namespacem1une{namespacegraph{namespacedetail{structChromaticResidues{staticconstexprstd::array<std::uint32_t,14>mod={1000000007,1000000009,998244353,985661441,943718401,935329793,918552577,897581057,880803841,754974721,645922817,595591169,469762049,167772161,};std::array<std::uint32_t,14>value;explicitChromaticResidues(std::uint32_tx=0){value.fill(x);}voidmultiply(std::uint32_tx){for(inti=0;i<int(mod.size());i++){value[i]=std::uint32_t(std::uint64_t(value[i])*x%mod[i]);}}};}// namespace detailtemplate<classT>intchromatic_number(constGraph<T>&g){intn=g.size();assert(n<=20);if(n==0)return0;std::vector<std::uint32_t>adjacent(n,0);for(constauto&e:g.edges()){if(e.from==e.to)continue;adjacent[e.from]|=std::uint32_t(1)<<e.to;adjacent[e.to]|=std::uint32_t(1)<<e.from;}std::uint32_tsubset_count=std::uint32_t(1)<<n;std::vector<std::uint32_t>independent_count(subset_count,0);independent_count[0]=1;for(std::uint32_tmask=1;mask<subset_count;mask++){intv=std::countr_zero(mask);std::uint32_trest=mask^(std::uint32_t(1)<<v);independent_count[mask]=independent_count[rest]+independent_count[rest&~adjacent[v]];}std::vector<detail::ChromaticResidues>power(subset_count,detail::ChromaticResidues(1));for(intcolors=1;colors<=n;colors++){std::array<std::uint32_t,14>sum={};for(std::uint32_tmask=0;mask<subset_count;mask++){power[mask].multiply(independent_count[mask]);boolpositive=((n-std::popcount(mask))&1)==0;for(inti=0;i<int(sum.size());i++){std::uint32_tx=power[mask].value[i];if(positive){sum[i]+=x;if(sum[i]>=detail::ChromaticResidues::mod[i]){sum[i]-=detail::ChromaticResidues::mod[i];}}else{sum[i]=(sum[i]>=x?sum[i]-x:sum[i]+detail::ChromaticResidues::mod[i]-x);}}}for(std::uint32_tx:sum){if(x!=0)returncolors;}}returnn;}}// namespace graph}// namespace m1une#line 1 "graph/complement_connected_components.hpp"
#line 6 "graph/complement_connected_components.hpp"
#line 1 "graph/connected_components.hpp"
#line 6 "graph/connected_components.hpp"
#line 1 "ds/dsu/dsu.hpp"
#line 8 "ds/dsu/dsu.hpp"
namespacem1une{namespaceds{structDsu{private:int_n;// parent_or_size[i] is the parent of i if it's >= 0.// If it's < 0, then i is a root and -parent_or_size[i] is the size of the group.std::vector<int>parent_or_size;// Returns {new leader, absorbed leader}. The absorbed leader is -1 when// both vertices already belong to the same component.std::pair<int,int>merge_leaders(inta,intb){intx=leader(a),y=leader(b);if(x==y)return{x,-1};if(-parent_or_size[x]<-parent_or_size[y])std::swap(x,y);parent_or_size[x]+=parent_or_size[y];parent_or_size[y]=x;return{x,y};}public:Dsu():_n(0){}explicitDsu(intn):_n(n),parent_or_size(n,-1){}// Merges the group containing 'a' with the group containing 'b'.// Returns the leader of the merged group.intmerge(inta,intb){returnmerge_leaders(a,b).first;}// Invokes callback(new_leader, absorbed_leader) after an actual merge.// Returns the leader of the merged group.template<classCallback>intmerge(inta,intb,Callback&&callback){std::pair<int,int>merged=merge_leaders(a,b);if(merged.second!=-1)callback(merged.first,merged.second);returnmerged.first;}// Returns true if 'a' and 'b' belong to the same group.boolsame(inta,intb){returnleader(a)==leader(b);}// Returns the leader (representative) of the group containing 'a'.intleader(inta){if(parent_or_size[a]<0)returna;// Path compressionreturnparent_or_size[a]=leader(parent_or_size[a]);}// Returns the size of the group containing 'a'.intsize(inta){return-parent_or_size[leader(a)];}// Returns a list of all groups, where each group is a vector of its elements.std::vector<std::vector<int>>groups(){std::vector<int>leader_buf(_n),group_size(_n);for(inti=0;i<_n;i++){leader_buf[i]=leader(i);group_size[leader_buf[i]]++;}std::vector<std::vector<int>>result(_n);for(inti=0;i<_n;i++){result[i].reserve(group_size[i]);}for(inti=0;i<_n;i++){result[leader_buf[i]].push_back(i);}result.erase(std::remove_if(result.begin(),result.end(),[&](conststd::vector<int>&v){returnv.empty();}),result.end());returnresult;}};}// namespace ds}// namespace m1une#line 9 "graph/connected_components.hpp"
namespacem1une{namespacegraph{structConnectedComponents{intcount;std::vector<int>comp;std::vector<std::vector<int>>groups;boolsame(intu,intv)const{assert(0<=u&&u<int(comp.size()));assert(0<=v&&v<int(comp.size()));returncomp[u]==comp[v];}};template<classT>ConnectedComponentsconnected_components(constGraph<T>&g){intn=g.size();m1une::ds::Dsudsu(n);for(constauto&e:g.edges())dsu.merge(e.from,e.to);ConnectedComponentsresult;result.comp.assign(n,0);std::vector<int>leader_to_comp(n,-1);for(intv=0;v<n;v++){intleader=dsu.leader(v);if(leader_to_comp[leader]==-1){leader_to_comp[leader]=int(result.groups.size());result.groups.push_back({});}intc=leader_to_comp[leader];result.comp[v]=c;result.groups[c].push_back(v);}result.count=int(result.groups.size());returnresult;}}// namespace graph}// namespace m1une#line 8 "graph/complement_connected_components.hpp"
namespacem1une{namespacegraph{// Computes connected components after complementing the underlying simple// undirected graph, without constructing the complement graph.template<classT>ConnectedComponentscomplement_connected_components(constGraph<T>&graph){constintsize=graph.size();std::vector<std::vector<int>>adjacency(size);for(constEdge<T>&edge:graph.edges()){if(edge.from==edge.to)continue;adjacency[edge.from].push_back(edge.to);adjacency[edge.to].push_back(edge.from);}constintsentinel=size;std::vector<int>next(size+1);std::vector<int>previous(size+1);if(size==0){next[sentinel]=previous[sentinel]=sentinel;}else{next[sentinel]=0;previous[sentinel]=size-1;for(intvertex=0;vertex<size;vertex++){next[vertex]=(vertex+1==size?sentinel:vertex+1);previous[vertex]=(vertex==0?sentinel:vertex-1);}}autoerase=[&](intvertex){next[previous[vertex]]=next[vertex];previous[next[vertex]]=previous[vertex];};ConnectedComponentsresult;result.comp.assign(size,-1);std::vector<int>neighbor_stamp(size,-1);std::queue<int>queue;while(next[sentinel]!=sentinel){constintroot=next[sentinel];erase(root);constintcomponent=int(result.groups.size());result.groups.emplace_back();result.groups.back().push_back(root);result.comp[root]=component;queue.push(root);while(!queue.empty()){constintvertex=queue.front();queue.pop();for(intto:adjacency[vertex])neighbor_stamp[to]=vertex;intcandidate=next[sentinel];while(candidate!=sentinel){constintfollowing=next[candidate];if(neighbor_stamp[candidate]!=vertex){erase(candidate);result.comp[candidate]=component;result.groups.back().push_back(candidate);queue.push(candidate);}candidate=following;}}}result.count=int(result.groups.size());returnresult;}}// namespace graph}// namespace m1une#line 1 "graph/count_four_cycles.hpp"
#line 6 "graph/count_four_cycles.hpp"
#include<tuple>
#line 9 "graph/count_four_cycles.hpp"
#line 11 "graph/count_four_cycles.hpp"
namespacem1une{namespacegraph{namespacefour_cycle_detail{// Counts C4s containing one particular copy of each edge in a simple graph// whose edge weights represent parallel-edge multiplicities.inlinestd::vector<longlong>count_simple_per_edge(intvertex_count,std::vector<int>first,std::vector<int>second,conststd::vector<longlong>&multiplicity){constintedge_count=int(first.size());assert(second.size()==first.size());assert(multiplicity.size()==first.size());std::vector<int>degree(vertex_count,0);for(intedge=0;edge<edge_count;edge++){degree[first[edge]]++;degree[second[edge]]++;}intmaximum_degree=0;for(intvalue:degree)maximum_degree=std::max(maximum_degree,value);std::vector<int>degree_start(maximum_degree+2,0);for(intvalue:degree)degree_start[value+1]++;for(intvalue=0;value<=maximum_degree;value++){degree_start[value+1]+=degree_start[value];}std::vector<int>cursor=degree_start;std::vector<int>order(vertex_count);for(intvertex=0;vertex<vertex_count;vertex++){order[cursor[degree[vertex]]++]=vertex;}std::vector<int>rank(vertex_count);for(inti=0;i<vertex_count;i++)rank[order[i]]=i;for(intedge=0;edge<edge_count;edge++){first[edge]=rank[first[edge]];second[edge]=rank[second[edge]];if(first[edge]<second[edge]){std::swap(first[edge],second[edge]);}}std::vector<int>start(vertex_count+1,0);for(intvertex=0;vertex<vertex_count;vertex++){start[vertex+1]=start[vertex]+degree[order[vertex]];}std::vector<int>end=start;std::vector<int>edge_at(2*edge_count);std::vector<int>to(2*edge_count);for(intedge=0;edge<edge_count;edge++){intposition=end[first[edge]]++;edge_at[position]=edge;to[position]=second[edge];}std::vector<int>downward_end=end;for(intvertex=0;vertex<vertex_count;vertex++){for(inti=start[vertex];i<downward_end[vertex];i++){intedge=edge_at[i];intneighbor=to[i];intposition=end[neighbor]++;edge_at[position]=edge;to[position]=vertex;}}std::vector<longlong>path_count(vertex_count,0);std::vector<longlong>result(edge_count,0);for(intvertex=vertex_count-1;vertex>=0;vertex--){for(inti=start[vertex];i<end[vertex];i++){intfirst_edge=edge_at[i];intmiddle=to[i];end[middle]--;for(intj=start[middle];j<end[middle];j++){intsecond_edge=edge_at[j];intopposite=to[j];path_count[opposite]+=multiplicity[first_edge]*multiplicity[second_edge];}}for(inti=start[vertex];i<end[vertex];i++){intfirst_edge=edge_at[i];intmiddle=to[i];for(intj=start[middle];j<end[middle];j++){intsecond_edge=edge_at[j];intopposite=to[j];longlongother_paths=path_count[opposite]-multiplicity[first_edge]*multiplicity[second_edge];result[first_edge]+=other_paths*multiplicity[second_edge];result[second_edge]+=other_paths*multiplicity[first_edge];}}for(inti=start[vertex];i<end[vertex];i++){intmiddle=to[i];for(intj=start[middle];j<end[middle];j++){path_count[to[j]]=0;}}}returnresult;}}// namespace four_cycle_detail// Returns, for every graph edge id, the number of C4 subgraphs containing it.// Parallel active edges are distinct choices; inactive edges receive zero.template<classT>std::vector<longlong>count_four_cycles_per_edge(constGraph<T>&graph){structActiveEdge{intfirst;intsecond;intid;};std::vector<ActiveEdge>active_edges;active_edges.reserve(graph.edge_count());for(constEdge<T>&edge:graph.edges()){assert(edge.from!=edge.to);assert(0<=edge.id&&edge.id<graph.edge_count());if(edge.from==edge.to)continue;active_edges.push_back(ActiveEdge{std::min(edge.from,edge.to),std::max(edge.from,edge.to),edge.id});}std::sort(active_edges.begin(),active_edges.end(),[](constActiveEdge&left,constActiveEdge&right){returnstd::tie(left.first,left.second)<std::tie(right.first,right.second);});std::vector<int>first;std::vector<int>second;std::vector<longlong>multiplicity;std::vector<int>group_of_edge(graph.edge_count(),-1);first.reserve(active_edges.size());second.reserve(active_edges.size());multiplicity.reserve(active_edges.size());for(constActiveEdge&edge:active_edges){if(first.empty()||first.back()!=edge.first||second.back()!=edge.second){first.push_back(edge.first);second.push_back(edge.second);multiplicity.push_back(0);}multiplicity.back()++;group_of_edge[edge.id]=int(first.size())-1;}std::vector<longlong>simple_result=four_cycle_detail::count_simple_per_edge(graph.size(),std::move(first),std::move(second),multiplicity);std::vector<longlong>result(graph.edge_count(),0);for(constActiveEdge&edge:active_edges){result[edge.id]=simple_result[group_of_edge[edge.id]];}returnresult;}template<classT>longlongcount_four_cycles(constGraph<T>&graph){std::vector<longlong>per_edge=count_four_cycles_per_edge(graph);longlongincidence_count=0;for(longlongcount:per_edge)incidence_count+=count;assert(incidence_count%4==0);returnincidence_count/4;}}// namespace graph}// namespace m1une#line 1 "graph/enumerate_cliques.hpp"
#line 8 "graph/enumerate_cliques.hpp"
#line 10 "graph/enumerate_cliques.hpp"
namespacem1une{namespacegraph{// Invokes callback once for every nonempty clique. The callback receives a// const reference to a temporary vector that is reused after it returns.template<classT,classCallback>voidenumerate_cliques(constGraph<T>&graph,Callback&&callback){constintn=graph.size();std::vector<std::vector<int>>adjacency(n);for(constEdge<T>&edge:graph.edges()){assert(edge.from!=edge.to);if(edge.from==edge.to)continue;adjacency[edge.from].push_back(edge.to);adjacency[edge.to].push_back(edge.from);}for(std::vector<int>&neighbors:adjacency){std::sort(neighbors.begin(),neighbors.end());#ifndef NDEBUG
for(inti=1;i<int(neighbors.size());i++){assert(neighbors[i-1]!=neighbors[i]);}#endif
neighbors.erase(std::unique(neighbors.begin(),neighbors.end()),neighbors.end());}intmaximum_degree=0;std::vector<int>degree(n);for(intvertex=0;vertex<n;vertex++){degree[vertex]=int(adjacency[vertex].size());maximum_degree=std::max(maximum_degree,degree[vertex]);}// Compute a degeneracy ordering in linear time. A clique is assigned to// its first vertex in this ordering, and all its other vertices are among// that vertex's forward neighbors.std::vector<std::vector<int>>bucket(maximum_degree+1);for(intvertex=0;vertex<n;vertex++){bucket[degree[vertex]].push_back(vertex);}std::vector<char>active(n,true);std::vector<std::vector<int>>forward(n);intminimum_degree=0;intdegeneracy=0;for(intremoved=0;removed<n;removed++){while(true){while(bucket[minimum_degree].empty())minimum_degree++;intvertex=bucket[minimum_degree].back();if(active[vertex]&°ree[vertex]==minimum_degree)break;bucket[minimum_degree].pop_back();}intvertex=bucket[minimum_degree].back();bucket[minimum_degree].pop_back();active[vertex]=false;degeneracy=std::max(degeneracy,minimum_degree);forward[vertex].reserve(minimum_degree);for(intto:adjacency[vertex]){if(!active[to])continue;forward[vertex].push_back(to);degree[to]--;bucket[degree[to]].push_back(to);minimum_degree=std::min(minimum_degree,degree[to]);}}std::vector<int>clique;clique.reserve(degeneracy+1);std::vector<std::vector<int>>candidates(degeneracy+1);for(intvertex=0;vertex<n;vertex++){conststd::vector<int>&neighbors=forward[vertex];constintneighbor_count=int(neighbors.size());clique.clear();clique.push_back(vertex);callback(std::as_const(clique));if(neighbor_count==0)continue;std::vector<char>connected(std::size_t(neighbor_count)*neighbor_count,false);for(intfirst=0;first<neighbor_count;first++){for(intsecond=first+1;second<neighbor_count;second++){booladjacent=std::binary_search(adjacency[neighbors[first]].begin(),adjacency[neighbors[first]].end(),neighbors[second]);connected[std::size_t(first)*neighbor_count+second]=adjacent;connected[std::size_t(second)*neighbor_count+first]=adjacent;}}candidates[0].resize(neighbor_count);for(inti=0;i<neighbor_count;i++)candidates[0][i]=i;autoenumerate=[&](auto&&self,intdepth)->void{conststd::vector<int>¤t=candidates[depth];for(intposition=0;position<int(current.size());position++){intchosen=current[position];clique.push_back(neighbors[chosen]);callback(std::as_const(clique));std::vector<int>&next=candidates[depth+1];next.clear();for(intnext_position=position+1;next_position<int(current.size());next_position++){intcandidate=current[next_position];if(connected[std::size_t(chosen)*neighbor_count+candidate]){next.push_back(candidate);}}if(!next.empty())self(self,depth+1);clique.pop_back();}};enumerate(enumerate,0);}}}// namespace graph}// namespace m1une#line 1 "graph/enumerate_triangles.hpp"
#line 7 "graph/enumerate_triangles.hpp"
#line 9 "graph/enumerate_triangles.hpp"
namespacem1une{namespacegraph{template<classT,classCallback>voidenumerate_triangles(constGraph<T>&graph,Callback&&callback){constintn=graph.size();conststd::vector<Edge<T>>edges=graph.edges();std::vector<int>degree(n,0);for(constEdge<T>&edge:edges){assert(edge.from!=edge.to);degree[edge.from]++;degree[edge.to]++;}std::vector<std::vector<int>>oriented(n);for(constEdge<T>&edge:edges){intfrom=edge.from;intto=edge.to;if(degree[from]>degree[to]||(degree[from]==degree[to]&&from>to)){std::swap(from,to);}oriented[from].push_back(to);}std::vector<int>marked(n,-1);for(intvertex=0;vertex<n;vertex++){for(intto:oriented[vertex])marked[to]=vertex;for(intmiddle:oriented[vertex]){for(intto:oriented[middle]){if(marked[to]!=vertex)continue;intfirst=vertex;intsecond=middle;intthird=to;if(first>second)std::swap(first,second);if(second>third)std::swap(second,third);if(first>second)std::swap(first,second);callback(first,second,third);}}}}}// namespace graph}// namespace m1une#line 1 "graph/general_matching.hpp"
#line 9 "graph/general_matching.hpp"
#line 11 "graph/general_matching.hpp"
namespacem1une{namespacegraph{structGeneralMatching{structEdge{intfrom;intto;intid;boolalive;intother(intv)const{assert(v==from||v==to);returnfrom^to^v;}};structPair{intfrom;intto;intedge_id;};private:int_n;std::vector<Edge>_edges;std::vector<std::vector<int>>_adj;std::vector<int>_mate;std::vector<int>_mate_edge;bool_calculated;voidinvalidate(){_calculated=false;}voidensure_matching(){if(!_calculated)max_matching();}boolis_matched_edge(intid)const{constauto&e=_edges[id];return_mate[e.from]==e.to&&_mate_edge[e.from]==id;}enumMatchingLabel:char{even_label,odd_label,unlabeled};structMutablePartition{std::vector<int>parent;std::vector<int>rank;std::vector<int>representative;MutablePartition()=default;explicitMutablePartition(intn){reset(n);}voidreset(intn){parent.resize(n);rank.assign(n,0);representative.resize(n);for(inti=0;i<n;i++){parent[i]=i;representative[i]=i;}}introot(intv){if(parent[v]==v)returnv;returnparent[v]=root(parent[v]);}intoperator()(intv){returnrepresentative[root(v)];}voidunite(inta,intb){intra=root(a);intrb=root(b);if(ra==rb)return;if(rank[ra]<rank[rb])std::swap(ra,rb);parent[rb]=ra;if(rank[ra]==rank[rb])rank[ra]++;}voidmake_rep(intv){representative[root(v)]=v;}};structEdgeBucketQueue{std::vector<std::vector<int>>bucket;std::vector<int>head;voidreset(intn){bucket.assign(n+3,{});head.assign(n+3,0);}voidinsert(intedge_id,intkey){if(key<0||int(bucket.size())<=key)return;bucket[key].push_back(edge_id);}intpop(intkey){if(key<0||int(bucket.size())<=key)return-1;if(head[key]==int(bucket[key].size()))return-1;returnbucket[key][head[key]++];}};structNewMatchingPair{intfrom;intto;intedge_id;};// General-graph shortest augmenting path phase solver.structMicaliVaziraniSolver{GeneralMatching&graph;intn;intmatching_size;intdelta;intvisit_token;inteven_time_token;MutablePartitionbase;MutablePartitiondelayed_base;EdgeBucketQueuequeue;std::vector<MatchingLabel>label;std::vector<MatchingLabel>h_label;std::vector<int>parent;std::vector<int>parent_edge;std::vector<int>source_bridge;std::vector<int>target_bridge;std::vector<int>bridge_edge;std::vector<int>lcp;std::vector<int>path_mark_1;std::vector<int>path_mark_2;std::vector<int>restore_vertex;std::vector<int>restore_value;std::vector<int>rep;std::vector<int>h_mate;std::vector<char>is_h_edge;std::vector<std::vector<int>>contracted_into;std::vector<int>h_parent_edge;std::vector<int>h_even_time;std::vector<int>h_bridge_edge;std::vector<int>h_bridge_dir;explicitMicaliVaziraniSolver(GeneralMatching&graph_):graph(graph_),n(graph_._n),matching_size(0),delta(0),visit_token(0),even_time_token(0),base(n),delayed_base(n),label(n,unlabeled),h_label(n,unlabeled),parent(n,-1),parent_edge(n,-1),source_bridge(n,-1),target_bridge(n,-1),bridge_edge(n,-1),lcp(n,0),path_mark_1(n,0),path_mark_2(n,0),rep(n,-1),h_mate(n,-1),is_h_edge(graph_._edges.size(),false),contracted_into(n),h_parent_edge(n,-1),h_even_time(n,0),h_bridge_edge(n,-1),h_bridge_dir(n,0){}boolactive(intedge_id)const{returngraph._edges[edge_id].alive;}intother(intedge_id,intv)const{returngraph._edges[edge_id].other(v);}intedge_weight(intedge_id)const{returngraph.is_matched_edge(edge_id)?2:0;}voidset_match(intedge_id){constauto&e=graph._edges[edge_id];graph._mate[e.from]=e.to;graph._mate[e.to]=e.from;graph._mate_edge[e.from]=edge_id;graph._mate_edge[e.to]=edge_id;}voidinitialize_greedy_matching(){graph._mate.assign(n,-1);graph._mate_edge.assign(n,-1);matching_size=0;for(constauto&e:graph._edges){if(!e.alive)continue;if(graph._mate[e.from]!=-1||graph._mate[e.to]!=-1)continue;set_match(e.id);matching_size++;}}voidscan_edge(intedge_id,intfrom){if(!active(edge_id))return;intto=other(edge_id,from);if(to==from||graph._mate[to]==from||label[base(to)]==odd_label)return;if(label[to]==unlabeled){queue.insert(edge_id,lcp[from]+2);}else{queue.insert(edge_id,(lcp[from]+lcp[to])/2+1);}}voidshrink_path(intblossom_base,intx,inty,intedge_id,std::vector<std::pair<int,int>>&delayed_unions){intv=base(x);while(v!=blossom_base){base.unite(v,blossom_base);delayed_unions.push_back({v,blossom_base});v=graph._mate[v];assert(v!=-1);base.unite(v,blossom_base);delayed_unions.push_back({v,blossom_base});base.make_rep(blossom_base);source_bridge[v]=x;target_bridge[v]=y;bridge_edge[v]=edge_id;restore_vertex.push_back(v);restore_value.push_back(lcp[v]);lcp[v]=lcp[x]+lcp[y]-lcp[graph._mate[v]]+2;for(intid:graph._adj[v])scan_edge(id,v);assert(parent[v]!=-1);v=base(parent[v]);}delayed_unions.push_back({blossom_base,blossom_base});}voidbuild_phase_graph(){std::fill(h_mate.begin(),h_mate.end(),-1);std::fill(is_h_edge.begin(),is_h_edge.end(),false);for(auto&vertices:contracted_into)vertices.clear();for(intv=0;v<n;v++)contracted_into[delayed_base(v)].push_back(v);for(constauto&e:graph._edges){if(!e.alive)continue;intu=e.from;intv=e.to;intuh=delayed_base(u);intvh=delayed_base(v);if(uh==vh)continue;if(label[uh]==odd_label&&label[vh]==odd_label)continue;intw=edge_weight(e.id);booleven_odd=(label[uh]==even_label&&label[vh]==odd_label&&lcp[v]==lcp[u]+1-w)||(label[vh]==even_label&&label[uh]==odd_label&&lcp[u]==lcp[v]+1-w);boolunlabeled_unlabeled=label[uh]==unlabeled&&label[vh]==unlabeled&&w==2;booleven_unlabeled=(label[uh]==even_label&&label[vh]==unlabeled&&lcp[u]==delta-2)||(label[vh]==even_label&&label[uh]==unlabeled&&lcp[v]==delta-2);booleven_even=label[uh]==even_label&&label[vh]==even_label;booltight_even_even=even_even&&lcp[u]+lcp[v]==2*delta+w-2;if(even_odd||unlabeled_unlabeled||even_unlabeled||tight_even_even){is_h_edge[e.id]=true;if(w==2){h_mate[uh]=vh;h_mate[vh]=uh;}}}}boolphase_one(){delta=0;base.reset(n);delayed_base.reset(n);queue.reset(n);std::fill(label.begin(),label.end(),unlabeled);std::fill(parent.begin(),parent.end(),-1);std::fill(parent_edge.begin(),parent_edge.end(),-1);std::fill(source_bridge.begin(),source_bridge.end(),-1);std::fill(target_bridge.begin(),target_bridge.end(),-1);std::fill(bridge_edge.begin(),bridge_edge.end(),-1);std::fill(lcp.begin(),lcp.end(),0);for(intv=0;v<n;v++){if(graph._mate[v]==-1)label[v]=even_label;}for(intv=0;v<n;v++){if(label[v]!=even_label)continue;for(intid:graph._adj[v])scan_edge(id,v);}std::vector<std::pair<int,int>>delayed_unions;while(delta<=n+1){restore_vertex.clear();restore_value.clear();while(true){intedge_id=queue.pop(delta);if(edge_id==-1)break;if(!active(edge_id))continue;intx=graph._edges[edge_id].from;inty=graph._edges[edge_id].to;if(label[base(x)]!=even_label)std::swap(x,y);if(label[base(x)]!=even_label)continue;if(graph._mate[x]==y||base(x)==base(y)||label[base(y)]==odd_label)continue;if(label[base(y)]==unlabeled){intz=graph._mate[y];assert(z!=-1);lcp[y]=lcp[x]+1;lcp[z]=lcp[x]+2;parent[y]=x;parent_edge[y]=edge_id;parent[z]=y;parent_edge[z]=graph._mate_edge[z];label[y]=odd_label;label[z]=even_label;for(intid:graph._adj[z])scan_edge(id,z);continue;}if(label[base(y)]!=even_label||lcp[x]+lcp[y]!=2*delta-2)continue;++visit_token;inthx=base(x);inthy=base(y);path_mark_1[hx]=visit_token;path_mark_2[hy]=visit_token;while(path_mark_1[hy]!=visit_token&&path_mark_2[hx]!=visit_token&&(graph._mate[hx]!=-1||graph._mate[hy]!=-1)){if(graph._mate[hx]!=-1){assert(parent[graph._mate[hx]]!=-1);hx=base(parent[graph._mate[hx]]);path_mark_1[hx]=visit_token;}if(graph._mate[hy]!=-1){assert(parent[graph._mate[hy]]!=-1);hy=base(parent[graph._mate[hy]]);path_mark_2[hy]=visit_token;}}if(path_mark_1[hy]==visit_token||path_mark_2[hx]==visit_token){intblossom_base=path_mark_1[hy]==visit_token?hy:hx;shrink_path(blossom_base,x,y,edge_id,delayed_unions);shrink_path(blossom_base,y,x,edge_id,delayed_unions);}else{for(inti=int(restore_vertex.size())-1;i>=0;i--){lcp[restore_vertex[i]]=restore_value[i];}build_phase_graph();returntrue;}}for(auto[a,b]:delayed_unions){if(a==b){delayed_base.make_rep(a);}else{delayed_base.unite(a,b);}}delayed_unions.clear();delta++;}returnfalse;}intnext_h_vertex_through_edge(intedge_id,intcurrent_h)const{constauto&e=graph._edges[edge_id];returnrep[rep[e.from]==current_h?e.to:e.from];}intfind_path_in_h(inth_vertex){for(intv:contracted_into[h_vertex]){for(intedge_id:graph._adj[v]){if(!is_h_edge[edge_id])continue;intuh=rep[other(edge_id,v)];if(h_mate[h_vertex]==uh)continue;if(h_label[uh]==unlabeled){intmate_uh=h_mate[uh];h_label[uh]=odd_label;h_parent_edge[uh]=edge_id;if(mate_uh==-1)returnuh;h_label[mate_uh]=even_label;h_even_time[mate_uh]=even_time_token++;intfound=find_path_in_h(mate_uh);if(found!=-1)returnfound;}else{intbh=delayed_base(h_vertex);intzh=delayed_base(uh);if(h_even_time[bh]>=h_even_time[zh])continue;std::vector<int>blossom_path;std::vector<int>blossom_vertices;while(zh!=bh){blossom_vertices.push_back(zh);zh=h_mate[zh];assert(zh!=-1);blossom_vertices.push_back(zh);blossom_path.push_back(zh);assert(h_parent_edge[zh]!=-1);zh=delayed_base(next_h_vertex_through_edge(h_parent_edge[zh],zh));}for(intx:blossom_vertices)delayed_base.unite(x,bh);delayed_base.make_rep(bh);std::reverse(blossom_path.begin(),blossom_path.end());for(intx:blossom_path){h_bridge_edge[x]=edge_id;h_bridge_dir[x]=graph._edges[edge_id].to==v?1:-1;}for(intx:blossom_path){intfound=find_path_in_h(x);if(found!=-1)returnfound;}}}}return-1;}voidcollect_path_in_h(std::vector<int>&path,intfrom_h,intto_h){if(from_h==to_h)return;if(h_label[from_h]==even_label){intmate_from=h_mate[from_h];assert(mate_from!=-1);intedge_id=h_parent_edge[mate_from];assert(edge_id!=-1);path.push_back(edge_id);collect_path_in_h(path,next_h_vertex_through_edge(edge_id,mate_from),to_h);}else{intedge_id=h_bridge_edge[from_h];assert(edge_id!=-1);constauto&e=graph._edges[edge_id];intfirst=rep[h_bridge_dir[from_h]==1?e.from:e.to];intsecond=rep[h_bridge_dir[from_h]==1?e.to:e.from];collect_path_in_h(path,first,rep[h_mate[from_h]]);path.push_back(edge_id);collect_path_in_h(path,second,to_h);}}voidadd_new_pair(std::vector<NewMatchingPair>&pairs,intfrom,intto,intedge_id)const{constauto&e=graph._edges[edge_id];assert(e.alive);assert((e.from==from&&e.to==to)||(e.from==to&&e.to==from));pairs.push_back(NewMatchingPair{from,to,edge_id});}voidcollect_path_in_graph(std::vector<NewMatchingPair>&pairs,intfrom,intto){if(from==to)return;if(label[from]==even_label){intmate_from=graph._mate[from];assert(mate_from!=-1);intparent_of_mate=parent[mate_from];intedge_id=parent_edge[mate_from];assert(parent_of_mate!=-1&&edge_id!=-1);add_new_pair(pairs,mate_from,parent_of_mate,edge_id);collect_path_in_graph(pairs,parent_of_mate,to);}else{assert(source_bridge[from]!=-1&&target_bridge[from]!=-1&&bridge_edge[from]!=-1);collect_path_in_graph(pairs,source_bridge[from],graph._mate[from]);add_new_pair(pairs,source_bridge[from],target_bridge[from],bridge_edge[from]);collect_path_in_graph(pairs,target_bridge[from],to);}}voidaugment_path(conststd::vector<int>&h_path){std::vector<NewMatchingPair>pairs;for(intedge_id:h_path){constauto&e=graph._edges[edge_id];add_new_pair(pairs,e.from,e.to,edge_id);collect_path_in_graph(pairs,e.from,rep[e.from]);collect_path_in_graph(pairs,e.to,rep[e.to]);}for(constauto&p:pairs){if(graph._mate[p.from]!=-1){intold=graph._mate[p.from];graph._mate[old]=-1;graph._mate_edge[old]=-1;}if(graph._mate[p.to]!=-1){intold=graph._mate[p.to];graph._mate[old]=-1;graph._mate_edge[old]=-1;}graph._mate[p.from]=graph._mate[p.to]=-1;graph._mate_edge[p.from]=graph._mate_edge[p.to]=-1;}for(constauto&p:pairs){assert(graph._mate[p.from]==-1&&graph._mate[p.to]==-1);graph._mate[p.from]=p.to;graph._mate[p.to]=p.from;graph._mate_edge[p.from]=p.edge_id;graph._mate_edge[p.to]=p.edge_id;}matching_size++;}voidphase_two(){std::fill(h_label.begin(),h_label.end(),unlabeled);std::fill(h_parent_edge.begin(),h_parent_edge.end(),-1);std::fill(h_bridge_edge.begin(),h_bridge_edge.end(),-1);std::fill(h_bridge_dir.begin(),h_bridge_dir.end(),0);for(intv=0;v<n;v++)rep[v]=delayed_base(v);std::vector<std::vector<int>>paths;for(inth_vertex=0;h_vertex<n;h_vertex++){if(rep[h_vertex]!=h_vertex)continue;if(h_label[h_vertex]!=unlabeled||h_mate[h_vertex]!=-1)continue;h_label[h_vertex]=even_label;h_even_time[h_vertex]=even_time_token++;intfree_h=find_path_in_h(h_vertex);if(free_h==-1)continue;std::vector<int>path;intedge_id=h_parent_edge[free_h];assert(edge_id!=-1);path.push_back(edge_id);collect_path_in_h(path,next_h_vertex_through_edge(edge_id,free_h),h_vertex);paths.push_back(path);}assert(!paths.empty());for(constauto&path:paths)augment_path(path);for(auto&vertices:contracted_into)vertices.clear();}intsolve(){initialize_greedy_matching();while(phase_one())phase_two();returnmatching_size;}};public:GeneralMatching():GeneralMatching(0){}explicitGeneralMatching(intn):_n(n),_adj(n),_mate(n,-1),_mate_edge(n,-1),_calculated(false){assert(0<=n);}intsize()const{return_n;}intedge_count()const{returnint(_edges.size());}intadd_edge(intfrom,intto){assert(0<=from&&from<_n);assert(0<=to&&to<_n);assert(from!=to);intid=int(_edges.size());_edges.push_back(Edge{from,to,id,true});_adj[from].push_back(id);_adj[to].push_back(id);invalidate();returnid;}Edgeget_edge(inti)const{assert(0<=i&&i<int(_edges.size()));return_edges[i];}std::vector<Edge>edges(boolinclude_inactive=false)const{std::vector<Edge>result;result.reserve(_edges.size());for(constauto&e:_edges){if(include_inactive||e.alive)result.push_back(e);}returnresult;}voidset_edge_alive(intid,boolalive){assert(0<=id&&id<int(_edges.size()));_edges[id].alive=alive;invalidate();}voiderase_edge(intid){set_edge_alive(id,false);}voidrevive_edge(intid){set_edge_alive(id,true);}boolis_edge_alive(intid)const{assert(0<=id&&id<int(_edges.size()));return_edges[id].alive;}intmax_matching(){MicaliVaziraniSolversolver(*this);intresult=solver.solve();_calculated=true;returnresult;}intmatching_size(){ensure_matching();intresult=0;for(intv=0;v<_n;v++){if(v<_mate[v])result++;}returnresult;}std::vector<int>mate(){ensure_matching();return_mate;}std::vector<int>mate_edge(){ensure_matching();return_mate_edge;}std::vector<Pair>matching(){ensure_matching();std::vector<Pair>result;for(intv=0;v<_n;v++){if(v<_mate[v])result.push_back(Pair{v,_mate[v],_mate_edge[v]});}returnresult;}std::optional<std::vector<int>>minimum_edge_cover(){ensure_matching();std::vector<int>result;std::vector<char>covered(_n,false),used_edge(_edges.size(),false);autouse_edge=[&](intid){if(used_edge[id])return;used_edge[id]=true;result.push_back(id);covered[_edges[id].from]=true;covered[_edges[id].to]=true;};for(intv=0;v<_n;v++){if(v<_mate[v])use_edge(_mate_edge[v]);}for(intv=0;v<_n;v++){if(covered[v])continue;intid=-1;for(intedge_id:_adj[v]){if(_edges[edge_id].alive){id=edge_id;break;}}if(id==-1)returnstd::nullopt;use_edge(id);}returnresult;}};structGeneralMatchingGraph{GeneralMatchingmatching;std::vector<int>original_edge_id;intoriginal_edge(intedge_id)const{assert(0<=edge_id&&edge_id<int(original_edge_id.size()));returnoriginal_edge_id[edge_id];}};template<classT>GeneralMatchingGraphmake_general_matching(constGraph<T>&g){GeneralMatchingGraphresult;result.matching=GeneralMatching(g.size());for(constauto&e:g.edges()){intid=result.matching.add_edge(e.from,e.to);if(int(result.original_edge_id.size())<=id)result.original_edge_id.resize(id+1);result.original_edge_id[id]=e.id;}returnresult;}}// namespace graph}// namespace m1une#line 1 "graph/general_weighted_matching.hpp"
#line 13 "graph/general_weighted_matching.hpp"
#line 15 "graph/general_weighted_matching.hpp"
namespacem1une{namespacegraph{namespaceinternal{// Primal-dual weighted blossom algorithm using Gabow's event queues.// Reference: H. N. Gabow, "Data Structures for Weighted Matching and// Extensions to b-matching and f-factors", 2016.// Vertices 1..n are atoms; larger indices represent contracted blossoms.template<classCost,classTotalCost>classWeightedBlossomSolver{public:usingcost_type=Cost;usingtotal_type=TotalCost;private:enumBlossomLabel:int{separated_label=-2,inner_label=-1,free_label=0,outer_label=1};staticconstexprcost_typeinfinity=cost_type(1)<<(sizeof(cost_type)*8-2);template<classT>classMutableBinaryHeap{public:structNode{booloperator<(constNode&rhs)const{if(value<rhs.value){returntrue;}if(rhs.value<value){returnfalse;}returnid<rhs.id;}Tvalue;intid;};MutableBinaryHeap()=default;explicitMutableBinaryHeap(intcapacity):_size(0),_nodes(capacity+1),_position(capacity,0){}boolempty()const{return_size==0;}voidclear(){while(_size>0){_position[_nodes[_size].id]=0;_size--;}}Tmin()const{return_nodes[1].value;}intargmin()const{return_nodes[1].id;}voidpop(){if(_size>0)pop(1);}voiderase(intid){if(_position[id])pop(_position[id]);}boolhas(intid)const{return_position[id]!=0;}voidupdate(intid,Tv){if(!has(id))returnpush(id,v);boolup=(v<_nodes[_position[id]].value);_nodes[_position[id]].value=v;if(up){up_heap(_position[id]);}else{down_heap(_position[id]);}}voiddecrease_key(intid,Tv){if(!has(id))returnpush(id,v);if(v<_nodes[_position[id]].value){_nodes[_position[id]].value=v;up_heap(_position[id]);}}voidpush(intid,Tv){_position[id]=++_size;_nodes[_size]={v,id};up_heap(_size);}private:voidpop(intpos){_position[_nodes[pos].id]=0;if(pos==_size){--_size;return;}boolup=(_nodes[_size].value<_nodes[pos].value);_nodes[pos]=_nodes[_size--];_position[_nodes[pos].id]=pos;if(up){up_heap(pos);}else{down_heap(pos);}}voidswap_node(inta,intb){std::swap(_nodes[a],_nodes[b]);_position[_nodes[a].id]=a;_position[_nodes[b].id]=b;}voiddown_heap(intpos){for(intcurrent=pos;;){intnext=current;if(2*current<=_size&&_nodes[2*current]<_nodes[next]){next=2*current;}if(2*current+1<=_size&&_nodes[2*current+1]<_nodes[next]){next=2*current+1;}if(next==current)break;swap_node(current,next);current=next;}}voidup_heap(intpos){for(intcurrent=pos;current>1&&_nodes[current]<_nodes[current>>1];current>>=1){swap_node(current,current>>1);}}int_size;std::vector<Node>_nodes;std::vector<int>_position;};template<classKey>classDisjointPairingHeaps{private:structNode{Node():key(),child(0),next(0),prev(-1){}explicitNode(Keyvalue):key(value),child(0),next(0),prev(0){}Keykey;intchild;intnext;intprev;};public:DisjointPairingHeaps(intheap_count,intnode_count):_roots(heap_count),_nodes(node_count){}voidclear(inth){if(_roots[h]){clear_rec(_roots[h]);_roots[h]=0;}}boolempty(inth)const{return!_roots[h];}boolused(intv)const{return_nodes[v].prev>=0;}Keymin(inth)const{return_nodes[_roots[h]].key;}voidpush(inth,intv,Keykey){_nodes[v]=Node(key);_roots[h]=merge(_roots[h],v);}voiderase(inth,intv){if(!used(v))return;intw=two_pass_pairing(_nodes[v].child);if(!_nodes[v].prev){_roots[h]=w;}else{cut(v);_roots[h]=merge(_roots[h],w);}_nodes[v].prev=-1;}voiddecrease_key(inth,intv,Keykey){if(!used(v))returnpush(h,v,key);if(!_nodes[v].prev){_nodes[v].key=key;}else{cut(v);_nodes[v].key=key;_roots[h]=merge(_roots[h],v);}}private:voidclear_rec(intv){for(;v;v=_nodes[v].next){if(_nodes[v].child)clear_rec(_nodes[v].child);_nodes[v].prev=-1;}}inlinevoidcut(intv){auto&n=_nodes[v];intprevious=n.prev;intnext=n.next;auto&previous_node=_nodes[previous];if(previous_node.child==v){previous_node.child=next;}else{previous_node.next=next;}_nodes[next].prev=previous;n.next=n.prev=0;}intmerge(intl,intr){if(!l)returnr;if(!r)returnl;if(_nodes[l].key>_nodes[r].key)std::swap(l,r);intlc=_nodes[r].next=_nodes[l].child;_nodes[l].child=_nodes[lc].prev=r;return_nodes[r].prev=l;}inttwo_pass_pairing(introot){if(!root)return0;inta=root;root=0;while(a){intb=_nodes[a].next;intnext_a=0;_nodes[a].prev=_nodes[a].next=0;if(b){next_a=_nodes[b].next;_nodes[b].prev=_nodes[b].next=0;}a=merge(a,b);_nodes[a].next=root;root=a;a=next_a;}ints=_nodes[root].next;_nodes[root].next=0;while(s){intt=_nodes[s].next;_nodes[s].next=0;root=merge(root,s);s=t;}returnroot;}private:std::vector<int>_roots;std::vector<Node>_nodes;};template<classT>structReservablePriorityQueue:publicstd::priority_queue<T,std::vector<T>,std::greater<T>>{ReservablePriorityQueue()=default;explicitReservablePriorityQueue(intcapacity){this->c.reserve(capacity);}Tmin()const{returnthis->top();}voidclear(){this->c.clear();}};template<classT>structFixedQueue{FixedQueue()=default;explicitFixedQueue(intcapacity):_head(0),_tail(0),_data(capacity){}voidenqueue(intu){_data[_tail++]=u;}intdequeue(){return_data[_head++];}boolempty()const{return_head==_tail;}voidclear(){_head=_tail=0;}int_head=0;int_tail=0;std::vector<T>_data;};public:structInputEdge{intfrom;intto;cost_typecost;};private:structSolverEdge{intto;cost_typecost;};structBlossomLink{intfrom;intto;};structBlossomNode{structCycleLink{intblossom;intvertex;};BlossomNode()=default;explicitBlossomNode(intvertex):parent(0),size(1){cycle[0]=cycle[1]=CycleLink{vertex,vertex};}intnext_v()const{returncycle[0].vertex;}intnext_b()const{returncycle[0].blossom;}intprev_v()const{returncycle[1].vertex;}intprev_b()const{returncycle[1].blossom;}intparent=0;intsize=0;CycleLinkcycle[2];};structVertexEvent{VertexEvent()=default;VertexEvent(cost_typeevent_time,intvertex):time(event_time),id(vertex){}booloperator<(constVertexEvent&rhs)const{if(time<rhs.time){returntrue;}if(rhs.time<time){returnfalse;}returnid<rhs.id;}booloperator>(constVertexEvent&rhs)const{returnrhs<*this;}cost_typetime=cost_type();intid=0;};structEdgeEvent{EdgeEvent()=default;EdgeEvent(cost_typeevent_time,intfrom_,intto_):time(event_time),from(from_),to(to_){}booloperator<(constEdgeEvent&rhs)const{if(time<rhs.time){returntrue;}if(time>rhs.time){returnfalse;}returnstd::make_pair(from,to)<std::make_pair(rhs.from,rhs.to);}booloperator>(constEdgeEvent&rhs)const{returnrhs<*this;}cost_typetime=cost_type();intfrom=0;intto=0;};public:WeightedBlossomSolver(intn,conststd::vector<InputEdge>&input_edges):_vertex_count(n),_blossom_count((n-1)/2),_state_count(n+_blossom_count+1),_offset(n+2),_edges(input_edges.size()*2),_grow_heap(_state_count),_blossom_grow_heaps(_state_count,_state_count),_contract_heap(int(_edges.size())),_expand_heap(_state_count){for(constInputEdge&edge:input_edges){_offset[edge.from+1]++;_offset[edge.to+1]++;}for(inti=1;i<=_vertex_count+1;i++)_offset[i]+=_offset[i-1];for(constInputEdge&edge:input_edges){_edges[_offset[edge.from]++]=SolverEdge{edge.to,edge.cost*2};_edges[_offset[edge.to]++]=SolverEdge{edge.from,edge.cost*2};}for(inti=_vertex_count+1;i>0;i--)_offset[i]=_offset[i-1];_offset[0]=0;}total_typesolve(std::vector<std::pair<int,int>>&matching){initialize_state();initialize_potentials();for(intvertex=1;vertex<=_vertex_count;vertex++){if(_mate[vertex]==0)augment_from(vertex);}matching.clear();for(intvertex=1;vertex<=_vertex_count;vertex++){if(_mate[vertex]>vertex)matching.emplace_back(vertex,_mate[vertex]);}returncompute_matching_weight();}private:total_typecompute_matching_weight()const{total_typeresult=0;for(intvertex=1;vertex<=_vertex_count;vertex++){if(_mate[vertex]>vertex){cost_typebest_cost=0;for(intedge_id=_offset[vertex];edge_id<_offset[vertex+1];edge_id++){if(_edges[edge_id].to==_mate[vertex]){best_cost=std::max(best_cost,_edges[edge_id].cost);}}result+=best_cost;}}returnresult>>1;}total_typereduced_cost(intfrom,intto,constSolverEdge&edge)const{returntotal_type(_potential[from])+_potential[to]-edge.cost;}voidrematch(intvertex,intnew_mate){intold_mate=_mate[vertex];_mate[vertex]=new_mate;if(_mate[old_mate]!=vertex)return;if(_tree_link[vertex].to==_surface[_tree_link[vertex].to]){_mate[old_mate]=_tree_link[vertex].from;rematch(_mate[old_mate],old_mate);}else{intfrom=_tree_link[vertex].from;intto=_tree_link[vertex].to;rematch(from,to);rematch(to,from);}}voidrepair_matching(intblossom){if(blossom<=_vertex_count)return;intchild=_base[blossom];intfirst_vertex=_nodes[child].cycle[0].vertex;intfirst_neighbor=_nodes[child].cycle[0].blossom;intdirection=(_nodes[first_neighbor].cycle[1].vertex==_mate[first_vertex])?0:1;while(true){intmatched_vertex=_nodes[child].cycle[direction].vertex;intmatched_child=_nodes[child].cycle[direction].blossom;if(_nodes[matched_child].cycle[1^direction].vertex!=_mate[matched_vertex])break;repair_matching(child);repair_matching(matched_child);child=_nodes[matched_child].cycle[direction].blossom;}_base[blossom]=child;repair_matching(child);_mate[blossom]=_mate[child];}voidreset_clock(){_time=0;_vertex_event={infinity,0};}voidreset_blossom(intblossom){_label[blossom]=free_label;_tree_link[blossom].from=0;_slack[blossom]=infinity;_lazy[blossom]=0;}voidreset_search_state(){_label[0]=free_label;_tree_link[0].from=0;for(intvertex=1;vertex<=_vertex_count;vertex++){if(_label[vertex]==outer_label){_potential[vertex]-=_time;}else{intblossom=_surface[vertex];_potential[vertex]+=_lazy[blossom];if(_label[blossom]==inner_label){_potential[vertex]+=_time-_created_at[blossom];}}reset_blossom(vertex);}intremaining_blossoms=_blossom_count-_unused_count;for(intblossom=_vertex_count+1;remaining_blossoms>0&&blossom<_state_count;blossom++){if(_base[blossom]!=blossom){if(_surface[blossom]==blossom){repair_matching(blossom);if(_label[blossom]==outer_label){_potential[blossom]+=(_time-_created_at[blossom])<<1;}elseif(_label[blossom]==inner_label){materialize_potential<inner_label>(blossom);}else{materialize_potential<free_label>(blossom);}}_blossom_grow_heaps.clear(blossom);reset_blossom(blossom);remaining_blossoms--;}}_queue.clear();reset_clock();_grow_heap.clear();_contract_heap.clear();_expand_heap.clear();}voidaugment_from(introot){if(_potential[root]==0)return;link_blossom(_surface[root],{0,0});make_outer(_surface[root],0);for(boolaugmented=false;!augmented;){augmented=scan_tight_edges(root);if(augmented)break;augmented=advance_dual(root);}reset_search_state();}template<BlossomLabeltarget_label>cost_typematerialize_potential(intblossom){cost_typedelta=_lazy[blossom];_lazy[blossom]=0;if(target_label==inner_label){cost_typeelapsed=_time-_created_at[blossom];if(blossom>_vertex_count)_potential[blossom]-=elapsed<<1;delta+=elapsed;}returndelta;}template<BlossomLabeltarget_label>voidupdate_grow_event(intfrom,intto,intto_blossom,cost_typeslack){if(slack>=_slack[to])return;_slack[to]=slack;_best_from[to]=from;if(to==to_blossom){if(target_label!=inner_label){_grow_heap.decrease_key(to,EdgeEvent(slack+_lazy[to],from,to));}}else{intto_group=_group[to];if(to_group!=to){if(slack>=_slack[to_group])return;_slack[to_group]=slack;}_blossom_grow_heaps.decrease_key(to_blossom,to_group,EdgeEvent(slack,from,to));if(target_label==inner_label)return;EdgeEventevent=_blossom_grow_heaps.min(to_blossom);_grow_heap.decrease_key(to_blossom,EdgeEvent(event.time+_lazy[to_blossom],event.from,event.to));}}voidactivate_grow_event(intblossom){if(blossom<=_vertex_count){if(_slack[blossom]<infinity){_grow_heap.push(blossom,EdgeEvent(_slack[blossom]+_lazy[blossom],_best_from[blossom],blossom));}}else{if(_blossom_grow_heaps.empty(blossom))return;EdgeEventevent=_blossom_grow_heaps.min(blossom);_grow_heap.push(blossom,EdgeEvent(event.time+_lazy[blossom],event.from,event.to));}}voidswap_blossoms(inta,intb){// b is a maximal blossom.std::swap(_base[a],_base[b]);if(_base[a]==a)_base[a]=b;std::swap(_heavy[a],_heavy[b]);if(_heavy[a]==a)_heavy[a]=b;std::swap(_tree_link[a],_tree_link[b]);std::swap(_mate[a],_mate[b]);std::swap(_potential[a],_potential[b]);std::swap(_lazy[a],_lazy[b]);std::swap(_created_at[a],_created_at[b]);for(intdirection=0;direction<2;direction++){intchild=_nodes[a].cycle[direction].blossom;_nodes[child].cycle[1^direction].blossom=b;}std::swap(_nodes[a],_nodes[b]);}voidassign_surface(intblossom,intsurface,intgroup){_surface[blossom]=surface;_group[blossom]=group;if(blossom<=_vertex_count)return;for(intchild=_base[blossom];_surface[child]!=surface;child=_nodes[child].next_b()){assign_surface(child,surface,group);}}voidmerge_blossom_children(intblossom){intlargest_child=blossom;intlargest_size=1;intfirst_child=_base[blossom];for(intchild=first_child;;child=_nodes[child].next_b()){if(_nodes[child].size>largest_size){largest_size=_nodes[child].size;largest_child=child;}if(_nodes[child].next_b()==first_child)break;}for(intchild=first_child;;child=_nodes[child].next_b()){if(child!=largest_child)assign_surface(child,largest_child,child);if(_nodes[child].next_b()==first_child)break;}_group[largest_child]=largest_child;if(largest_size>1){_surface[blossom]=_heavy[blossom]=largest_child;swap_blossoms(largest_child,blossom);}else{_heavy[blossom]=0;}}voidcontract_blossom(intx,inty,intedge_id){intx_blossom=_surface[x];inty_blossom=_surface[y];assert(x_blossom!=y_blossom);constintvisit_mark=-(edge_id+1);_tree_link[_surface[_mate[x_blossom]]].from=visit_mark;_tree_link[_surface[_mate[y_blossom]]].from=visit_mark;intlca=-1;while(true){if(_mate[y_blossom]!=0)std::swap(x_blossom,y_blossom);x_blossom=lca=_surface[_tree_link[x_blossom].from];if(_tree_link[_surface[_mate[x_blossom]]].from==visit_mark)break;_tree_link[_surface[_mate[x_blossom]]].from=visit_mark;}constintblossom=_unused_blossoms[--_unused_count];assert(_unused_count>=0);inttree_size=0;for(intdirection=0;direction<2;direction++){for(intchild=_surface[x];child!=lca;){intmatched_vertex=_mate[child];intmatched_child=_surface[matched_vertex];intvertex=_mate[matched_vertex];intlink_from=_tree_link[vertex].from;intlink_to=_tree_link[vertex].to;tree_size+=_nodes[child].size+_nodes[matched_child].size;_tree_link[matched_vertex]={x,y};if(child>_vertex_count){_potential[child]+=(_time-_created_at[child])<<1;}if(matched_child>_vertex_count)_expand_heap.erase(matched_child);make_outer(matched_child,materialize_potential<inner_label>(matched_child));_nodes[child].cycle[direction]={matched_child,matched_vertex};_nodes[matched_child].cycle[1^direction]={child,vertex};child=_surface[link_from];_nodes[matched_child].cycle[direction]={child,link_from};_nodes[child].cycle[1^direction]={matched_child,link_to};}_nodes[_surface[x]].cycle[1^direction]={_surface[y],y};std::swap(x,y);}if(lca>_vertex_count)_potential[lca]+=(_time-_created_at[lca])<<1;_nodes[blossom].size=tree_size+_nodes[lca].size;_base[blossom]=lca;_tree_link[blossom]=_tree_link[lca];_mate[blossom]=_mate[lca];_label[blossom]=outer_label;_surface[blossom]=blossom;_created_at[blossom]=_time;_potential[blossom]=0;_lazy[blossom]=0;merge_blossom_children(blossom);}voidlink_blossom(intblossom,BlossomLinklink){_tree_link[blossom]=link;if(blossom<=_vertex_count)return;intfirst_child=_base[blossom];link_blossom(first_child,link);intprevious_child=_nodes[first_child].prev_b();link={_nodes[previous_child].next_v(),_nodes[first_child].prev_v()};for(intchild=first_child;;){intnext_child=_nodes[child].next_b();if(next_child==first_child)break;link_blossom(next_child,link);BlossomLinknext_link={_nodes[next_child].prev_v(),_nodes[child].next_v()};child=_nodes[next_child].next_b();link_blossom(child,next_link);}}voidmake_outer(intblossom,cost_typedelta){_label[blossom]=outer_label;if(blossom>_vertex_count){for(intchild=_base[blossom];_label[child]!=outer_label;child=_nodes[child].next_b()){make_outer(child,delta);}}else{_potential[blossom]+=_time+delta;if(_potential[blossom]<_vertex_event.time){_vertex_event={_potential[blossom],blossom};}_queue.enqueue(blossom);}}boolgrow_tree(intfrom,intto){intinner_blossom=_surface[to];boolvisited=(_label[inner_blossom]!=free_label);if(!visited)link_blossom(inner_blossom,{0,0});_label[inner_blossom]=inner_label;_created_at[inner_blossom]=_time;_grow_heap.erase(inner_blossom);if(to!=inner_blossom){_expand_heap.update(inner_blossom,_time+(_potential[inner_blossom]>>1));}intmatched_vertex=_mate[inner_blossom];if(matched_vertex==0){rematch(from,to);rematch(to,from);returntrue;}intouter_blossom=_surface[matched_vertex];if(!visited){link_blossom(outer_blossom,{from,to});}else{_tree_link[outer_blossom]=_tree_link[matched_vertex]={from,to};}make_outer(outer_blossom,materialize_potential<free_label>(outer_blossom));_created_at[outer_blossom]=_time;_grow_heap.erase(outer_blossom);returnfalse;}voidrelease_blossom(intblossom){_unused_blossoms[_unused_count++]=blossom;_base[blossom]=blossom;}intrecompute_slack(intblossom,intgroup){if(blossom<=_vertex_count){if(_slack[blossom]>=_slack[group])return0;_slack[group]=_slack[blossom];_best_from[group]=_best_from[blossom];returnblossom;}intdestination=0;intfirst_child=_base[blossom];for(intchild=first_child;;child=_nodes[child].next_b()){intcandidate=recompute_slack(child,group);if(candidate!=0)destination=candidate;if(_nodes[child].next_b()==first_child)break;}returndestination;}voidrebuild_components(intblossom,intsurface,intgroup){_surface[blossom]=surface;_group[blossom]=group;if(blossom<=_vertex_count)return;for(intchild=_base[blossom];_surface[child]!=surface;child=_nodes[child].next_b()){if(child==_heavy[blossom]){rebuild_components(child,surface,group);}else{assign_surface(child,surface,child);intdestination=0;if(child>_vertex_count){_slack[child]=infinity;destination=recompute_slack(child,child);}elseif(_slack[child]<infinity){destination=child;}if(destination>0){_blossom_grow_heaps.push(surface,child,EdgeEvent(_slack[child],_best_from[child],destination));}}}}voidpromote_largest_child(intblossom){intlargest_child=_heavy[blossom];cost_typedelta=(_time-_created_at[blossom])+_lazy[blossom];_lazy[blossom]=0;intfirst_child=_base[blossom];for(intchild=first_child;;child=_nodes[child].next_b()){_created_at[child]=_time;_lazy[child]=delta;if(child!=largest_child){rebuild_components(child,child,child);_blossom_grow_heaps.erase(blossom,child);}if(_nodes[child].next_b()==first_child)break;}if(largest_child>0){swap_blossoms(largest_child,blossom);blossom=largest_child;}release_blossom(blossom);}voidexpand_blossom(intblossom){intmatched_vertex=_mate[_base[blossom]];promote_largest_child(blossom);BlossomLinkold_link=_tree_link[matched_vertex];intold_base=_surface[_mate[matched_vertex]];introot=_surface[old_link.to];intdirection=(_mate[root]==_nodes[root].cycle[0].vertex)?1:0;for(intchild=_nodes[old_base].cycle[direction^1].blossom;child!=root;){_label[child]=separated_label;activate_grow_event(child);child=_nodes[child].cycle[direction^1].blossom;_label[child]=separated_label;activate_grow_event(child);child=_nodes[child].cycle[direction^1].blossom;}for(intchild=old_base;;child=_nodes[child].cycle[direction].blossom){_label[child]=inner_label;intnext_child=_nodes[child].cycle[direction].blossom;if(child==root){_tree_link[_mate[child]]=old_link;}else{_tree_link[_mate[child]]={_nodes[child].cycle[direction].vertex,_nodes[next_child].cycle[direction^1].vertex};}_tree_link[_surface[_mate[child]]]=_tree_link[_mate[child]];if(child>_vertex_count){if(_potential[child]==0){expand_blossom(child);}else{_expand_heap.push(child,_time+(_potential[child]>>1));}}if(child==root)break;child=next_child;make_outer(next_child,materialize_potential<inner_label>(next_child));}}boolscan_tight_edges(introot){while(!_queue.empty()){intfrom=_queue.dequeue();intfrom_blossom=_surface[from];if(_potential[from]==_time){if(from!=root)rematch(from,0);returntrue;}for(intedge_id=_offset[from];edge_id<_offset[from+1];edge_id++){constSolverEdge&edge=_edges[edge_id];intto=edge.to;intto_blossom=_surface[to];if(from_blossom==to_blossom)continue;BlossomLabelto_label=_label[to_blossom];if(to_label==outer_label){cost_typeevent_time=cost_type(reduced_cost(from,to,edge)>>1);if(event_time==_time){contract_blossom(from,to,edge_id);from_blossom=_surface[from];}elseif(event_time<_vertex_event.time){_contract_heap.emplace(event_time,from,edge_id);}}else{total_typeevent_time=reduced_cost(from,to,edge);if(event_time>=infinity)continue;if(to_label!=inner_label){if(cost_type(event_time)+_lazy[to_blossom]==_time){if(grow_tree(from,to))returntrue;}else{update_grow_event<free_label>(from,to,to_blossom,cost_type(event_time));}}elseif(_mate[from]!=to){update_grow_event<inner_label>(from,to,to_blossom,cost_type(event_time));}}}}returnfalse;}booladvance_dual(introot){cost_typerematch_time=_vertex_event.time;cost_typegrow_time=infinity;if(!_grow_heap.empty())grow_time=_grow_heap.min().time;cost_typecontract_time=infinity;while(!_contract_heap.empty()){EdgeEventevent=_contract_heap.min();intfrom=event.from;intto=_edges[event.to].to;if(_surface[from]!=_surface[to]){contract_time=event.time;break;}else{_contract_heap.pop();}}cost_typeexpand_time=infinity;if(!_expand_heap.empty())expand_time=_expand_heap.min();cost_typenext_time=std::min(std::min(rematch_time,grow_time),std::min(contract_time,expand_time));assert(_time<=next_time&&next_time<infinity);_time=next_time;if(_time==_vertex_event.time){intx=_vertex_event.id;if(x!=root)rematch(x,0);returntrue;}while(!_grow_heap.empty()&&_grow_heap.min().time==_time){intfrom=_grow_heap.min().from;intto=_grow_heap.min().to;if(grow_tree(from,to))returntrue;}while(!_contract_heap.empty()&&_contract_heap.min().time==_time){intfrom=_contract_heap.min().from;intedge_id=_contract_heap.min().to;intto=_edges[edge_id].to;_contract_heap.pop();if(_surface[from]==_surface[to])continue;contract_blossom(from,to,edge_id);}while(!_expand_heap.empty()&&_expand_heap.min()==_time){intblossom=_expand_heap.argmin();_expand_heap.pop();expand_blossom(blossom);}returnfalse;}private:voidinitialize_state(){_queue=FixedQueue<int>(_vertex_count);_mate.assign(_state_count,0);_tree_link.assign(_state_count,{0,0});_label.assign(_state_count,free_label);_base.resize(_state_count);for(intstate=1;state<_state_count;state++)_base[state]=state;_surface.resize(_state_count);for(intstate=1;state<_state_count;state++)_surface[state]=state;_potential.resize(_state_count);_nodes.resize(_state_count);for(intstate=1;state<_state_count;state++){_nodes[state]=BlossomNode(state);}_unused_blossoms.resize(_blossom_count);for(inti=0;i<_blossom_count;i++){_unused_blossoms[i]=_vertex_count+_blossom_count-i;}_unused_count=_blossom_count;reset_clock();_created_at.resize(_state_count);_slack.assign(_state_count,infinity);_best_from.assign(_state_count,0);_heavy.assign(_state_count,0);_lazy.assign(_state_count,0);_group.resize(_state_count);for(intstate=0;state<_state_count;state++)_group[state]=state;}voidinitialize_potentials(){for(intvertex=1;vertex<=_vertex_count;vertex++){cost_typemaximum_cost=0;for(intedge_id=_offset[vertex];edge_id<_offset[vertex+1];edge_id++){maximum_cost=std::max(maximum_cost,_edges[edge_id].cost);}_potential[vertex]=maximum_cost>>1;}}constint_vertex_count;constint_blossom_count;constint_state_count;std::vector<int>_offset;std::vector<SolverEdge>_edges;FixedQueue<int>_queue;std::vector<int>_mate;std::vector<int>_surface;std::vector<int>_base;std::vector<BlossomLink>_tree_link;std::vector<BlossomLabel>_label;std::vector<cost_type>_potential;std::vector<int>_unused_blossoms;int_unused_count;std::vector<BlossomNode>_nodes;// Heavy children and event queues keep each search phase at O(m log n).std::vector<int>_heavy;std::vector<int>_group;std::vector<cost_type>_created_at;std::vector<cost_type>_lazy;std::vector<cost_type>_slack;std::vector<int>_best_from;cost_type_time;VertexEvent_vertex_event;MutableBinaryHeap<EdgeEvent>_grow_heap;DisjointPairingHeaps<EdgeEvent>_blossom_grow_heaps;ReservablePriorityQueue<EdgeEvent>_contract_heap;MutableBinaryHeap<cost_type>_expand_heap;};}// namespace internaltemplate<classCost,classTotalCost=Cost>structGeneralWeightedMatching{static_assert(std::is_integral_v<Cost>&&std::is_signed_v<Cost>);static_assert(std::is_integral_v<TotalCost>&&std::is_signed_v<TotalCost>);structEdge{intfrom;intto;Costcost;intid;boolalive;intother(intvertex)const{assert(vertex==from||vertex==to);returnfrom^to^vertex;}};structPair{intfrom;intto;Costcost;intedge_id;};private:int_n;std::vector<Edge>_edges;std::vector<std::vector<int>>_adj;std::vector<int>_mate;std::vector<int>_mate_edge;TotalCost_matching_weight;bool_calculated;voidinvalidate(){_calculated=false;}voidensure_matching(){if(!_calculated)max_weight_matching();}public:GeneralWeightedMatching():GeneralWeightedMatching(0){}explicitGeneralWeightedMatching(intn):_n(n),_adj(n),_mate(n,-1),_mate_edge(n,-1),_matching_weight(),_calculated(false){assert(0<=n);}intsize()const{return_n;}intedge_count()const{returnint(_edges.size());}intadd_edge(intfrom,intto,Costcost){assert(0<=from&&from<_n);assert(0<=to&&to<_n);assert(from!=to);assert(cost<=std::numeric_limits<Cost>::max()/Cost(2));intid=int(_edges.size());_edges.push_back(Edge{from,to,cost,id,true});_adj[from].push_back(id);_adj[to].push_back(id);invalidate();returnid;}Edgeget_edge(intid)const{assert(0<=id&&id<int(_edges.size()));return_edges[id];}std::vector<Edge>edges(boolinclude_inactive=false)const{std::vector<Edge>result;result.reserve(_edges.size());for(constEdge&edge:_edges){if(include_inactive||edge.alive)result.push_back(edge);}returnresult;}voidset_edge_alive(intid,boolalive){assert(0<=id&&id<int(_edges.size()));_edges[id].alive=alive;invalidate();}voiderase_edge(intid){set_edge_alive(id,false);}voidrevive_edge(intid){set_edge_alive(id,true);}boolis_edge_alive(intid)const{assert(0<=id&&id<int(_edges.size()));return_edges[id].alive;}TotalCostmax_weight_matching(){usingSolver=internal::WeightedBlossomSolver<Cost,TotalCost>;std::vector<typenameSolver::InputEdge>input;input.reserve(_edges.size());for(constEdge&edge:_edges){if(!edge.alive||edge.cost<=Cost())continue;input.push_back(typenameSolver::InputEdge{edge.from+1,edge.to+1,edge.cost});}Solversolver(_n,input);std::vector<std::pair<int,int>>vertex_pairs;solver.solve(vertex_pairs);_mate.assign(_n,-1);_mate_edge.assign(_n,-1);_matching_weight=TotalCost();for(auto[one_based_from,one_based_to]:vertex_pairs){intfrom=one_based_from-1;intto=one_based_to-1;intbest_edge=-1;for(intid:_adj[from]){constEdge&edge=_edges[id];if(!edge.alive||edge.other(from)!=to||edge.cost<=Cost())continue;if(best_edge==-1||_edges[best_edge].cost<edge.cost)best_edge=id;}assert(best_edge!=-1);_mate[from]=to;_mate[to]=from;_mate_edge[from]=best_edge;_mate_edge[to]=best_edge;_matching_weight+=static_cast<TotalCost>(_edges[best_edge].cost);}_calculated=true;return_matching_weight;}TotalCostmatching_weight(){ensure_matching();return_matching_weight;}intmatching_size(){ensure_matching();intresult=0;for(intvertex=0;vertex<_n;vertex++){if(vertex<_mate[vertex])result++;}returnresult;}std::vector<int>mate(){ensure_matching();return_mate;}std::vector<int>mate_edge(){ensure_matching();return_mate_edge;}std::vector<Pair>matching(){ensure_matching();std::vector<Pair>result;for(intvertex=0;vertex<_n;vertex++){if(vertex<_mate[vertex]){intid=_mate_edge[vertex];result.push_back(Pair{vertex,_mate[vertex],_edges[id].cost,id});}}returnresult;}};template<classCost,classTotalCost=Cost>structGeneralWeightedMatchingGraph{GeneralWeightedMatching<Cost,TotalCost>matching;std::vector<int>original_edge_id;intoriginal_edge(intedge_id)const{assert(0<=edge_id&&edge_id<int(original_edge_id.size()));returnoriginal_edge_id[edge_id];}};template<classT>GeneralWeightedMatchingGraph<T>make_general_weighted_matching(constGraph<T>&graph){GeneralWeightedMatchingGraph<T>result;result.matching=GeneralWeightedMatching<T>(graph.size());for(constauto&edge:graph.edges()){intid=result.matching.add_edge(edge.from,edge.to,edge.cost);if(int(result.original_edge_id.size())<=id){result.original_edge_id.resize(id+1);}result.original_edge_id[id]=edge.id;}returnresult;}}// namespace graph}// namespace m1une#line 1 "graph/kruskal.hpp"
#line 6 "graph/kruskal.hpp"
#line 9 "graph/kruskal.hpp"
namespacem1une{namespacegraph{template<classT>structMinimumSpanningForest{Tcost;std::vector<Edge<T>>edges;intcomponents;boolis_spanning_tree(intn)const{returncomponents<=1&&int(edges.size())==std::max(0,n-1);}};template<classT>MinimumSpanningForest<T>kruskal(constGraph<T>&g){intn=g.size();autoedges=g.edges();std::sort(edges.begin(),edges.end(),[](constauto&a,constauto&b){returna.cost<b.cost;});m1une::ds::Dsudsu(n);MinimumSpanningForest<T>result;result.cost=T(0);result.components=n;for(constauto&e:edges){if(dsu.same(e.from,e.to))continue;dsu.merge(e.from,e.to);result.cost+=e.cost;result.edges.push_back(e);result.components--;}returnresult;}}// namespace graph}// namespace m1une#line 1 "graph/lowlink.hpp"
#line 6 "graph/lowlink.hpp"
#line 8 "graph/lowlink.hpp"
namespacem1une{namespacegraph{template<classT>structLowLinkResult{std::vector<int>ord;std::vector<int>low;std::vector<int>articulation;std::vector<Edge<T>>bridges;std::vector<int>bridge_ids;};template<classT>LowLinkResult<T>lowlink(constGraph<T>&g){intn=g.size();LowLinkResult<T>result;result.ord.assign(n,-1);result.low.assign(n,-1);intnow=0;autodfs=[&](autoself,intv,intparent_edge)->void{result.ord[v]=result.low[v]=now++;intchild_count=0;boolis_articulation=false;for(constauto&e:g[v]){if(!e.alive)continue;if(e.id==parent_edge)continue;intto=e.to;if(result.ord[to]==-1){child_count++;self(self,to,e.id);result.low[v]=std::min(result.low[v],result.low[to]);if(parent_edge!=-1&&result.ord[v]<=result.low[to])is_articulation=true;if(result.ord[v]<result.low[to]){result.bridges.push_back(e);result.bridge_ids.push_back(e.id);}}else{result.low[v]=std::min(result.low[v],result.ord[to]);}}if(parent_edge==-1&&child_count>=2)is_articulation=true;if(is_articulation)result.articulation.push_back(v);};for(intv=0;v<n;v++){if(result.ord[v]==-1)dfs(dfs,v,-1);}std::sort(result.articulation.begin(),result.articulation.end());std::sort(result.bridge_ids.begin(),result.bridge_ids.end());returnresult;}}// namespace graph}// namespace m1une#line 1 "graph/maximum_clique.hpp"
#line 7 "graph/maximum_clique.hpp"
#line 9 "graph/maximum_clique.hpp"
namespacem1une{namespacegraph{structMaximumCliqueResult{std::vector<int>vertices;intsize()const{returnint(vertices.size());}boolempty()const{returnvertices.empty();}};structMaximumIndependentSetResult{std::vector<int>vertices;intsize()const{returnint(vertices.size());}boolempty()const{returnvertices.empty();}};structMinimumVertexCoverResult{std::vector<int>vertices;intsize()const{returnint(vertices.size());}boolempty()const{returnvertices.empty();}};namespacedetail{structMaximumIndependentSetBranching{intn;std::vector<std::vector<char>>adjacent;std::vector<std::vector<int>>graph;explicitMaximumIndependentSetBranching(conststd::vector<std::vector<char>>&adjacent_):n(int(adjacent_.size())),adjacent(adjacent_),graph(n){for(intv=0;v<n;v++){for(intto=0;to<n;to++){if(adjacent[v][to])graph[v].push_back(to);}}}std::vector<int>solve_path(conststd::vector<int>&order)const{intm=int(order.size());if(m==0)return{};std::vector<int>dp0(m,0),dp1(m,0);dp1[0]=1;for(inti=1;i<m;i++){dp0[i]=std::max(dp0[i-1],dp1[i-1]);dp1[i]=dp0[i-1]+1;}std::vector<int>result;intstate=(dp1[m-1]>dp0[m-1]?1:0);for(inti=m-1;i>=0;i--){if(state==1){result.push_back(order[i]);state=0;}elseif(i>0){state=(dp1[i-1]>dp0[i-1]?1:0);}}returnresult;}std::vector<int>solve_cycle(conststd::vector<int>&order)const{intm=int(order.size());if(m==0)return{};if(m==1)return{order[0]};std::vector<int>without_first(order.begin()+1,order.end());autoresult_without=solve_path(without_first);std::vector<int>result_with={order[0]};if(m>=4){std::vector<int>middle(order.begin()+2,order.end()-1);automiddle_result=solve_path(middle);result_with.insert(result_with.end(),middle_result.begin(),middle_result.end());}return(result_with.size()>result_without.size()?result_with:result_without);}std::vector<int>solve_degree_at_most_two(conststd::vector<char>&active,conststd::vector<int>°ree)const{std::vector<int>result;std::vector<char>visited(n,false);for(ints=0;s<n;s++){if(!active[s]||visited[s])continue;std::vector<int>component;std::vector<int>stack={s};visited[s]=true;for(intit=0;it<int(stack.size());it++){intv=stack[it];component.push_back(v);for(intto:graph[v]){if(!active[to]||visited[to])continue;visited[to]=true;stack.push_back(to);}}if(component.size()==1){result.push_back(component[0]);continue;}intendpoint=-1;for(intv:component){if(degree[v]<=1){endpoint=v;break;}}std::vector<int>order;if(endpoint!=-1){intprev=-1,cur=endpoint;while(cur!=-1){order.push_back(cur);intnext=-1;for(intto:graph[cur]){if(active[to]&&to!=prev){next=to;break;}}prev=cur;cur=next;}autopart=solve_path(order);result.insert(result.end(),part.begin(),part.end());}else{intstart=component[0];intfirst=-1;for(intto:graph[start]){if(active[to]){first=to;break;}}assert(first!=-1);order.push_back(start);intprev=start,cur=first;while(cur!=start){order.push_back(cur);intnext=-1;for(intto:graph[cur]){if(active[to]&&to!=prev){next=to;break;}}assert(next!=-1);prev=cur;cur=next;}autopart=solve_cycle(order);result.insert(result.end(),part.begin(),part.end());}}returnresult;}std::vector<int>solve(std::vector<char>active)const{intactive_count=0;intmax_degree=-1;intbranch_vertex=-1;std::vector<int>degree(n,0);for(intv=0;v<n;v++){if(!active[v])continue;active_count++;for(intto:graph[v]){if(active[to])degree[v]++;}if(degree[v]>max_degree){max_degree=degree[v];branch_vertex=v;}}if(active_count==0)return{};if(max_degree<=2){autoresult=solve_degree_at_most_two(active,degree);std::sort(result.begin(),result.end());returnresult;}autowithout=active;without[branch_vertex]=false;autoresult_without=solve(without);autowith=active;with[branch_vertex]=false;for(intto:graph[branch_vertex])with[to]=false;autoresult_with=solve(with);result_with.push_back(branch_vertex);autoresult=(result_with.size()>result_without.size()?result_with:result_without);std::sort(result.begin(),result.end());returnresult;}std::vector<int>solve()const{std::vector<char>active(n,true);returnsolve(active);}};template<classT>std::vector<std::vector<char>>undirected_adjacency_matrix(constGraph<T>&g){intn=g.size();std::vector<std::vector<char>>adjacent(n,std::vector<char>(n,false));for(constauto&e:g.edges()){if(e.from==e.to)continue;adjacent[e.from][e.to]=true;adjacent[e.to][e.from]=true;}returnadjacent;}std::vector<std::vector<char>>complement_adjacency_matrix(conststd::vector<std::vector<char>>&adjacent){intn=int(adjacent.size());std::vector<std::vector<char>>complement(n,std::vector<char>(n,false));for(inti=0;i<n;i++){for(intj=i+1;j<n;j++){if(adjacent[i][j])continue;complement[i][j]=true;complement[j][i]=true;}}returncomplement;}}// namespace detailtemplate<classT>boolis_clique(constGraph<T>&g,conststd::vector<int>&vertices){autoadjacent=detail::undirected_adjacency_matrix(g);for(intv:vertices){assert(0<=v&&v<g.size());}for(inti=0;i<int(vertices.size());i++){for(intj=i+1;j<int(vertices.size());j++){if(!adjacent[vertices[i]][vertices[j]])returnfalse;}}returntrue;}template<classT>boolis_independent_set(constGraph<T>&g,conststd::vector<int>&vertices){autoadjacent=detail::undirected_adjacency_matrix(g);for(intv:vertices){assert(0<=v&&v<g.size());}for(inti=0;i<int(vertices.size());i++){for(intj=i+1;j<int(vertices.size());j++){if(adjacent[vertices[i]][vertices[j]])returnfalse;}}returntrue;}template<classT>boolis_vertex_cover(constGraph<T>&g,conststd::vector<int>&vertices){std::vector<char>selected(g.size(),false);for(intv:vertices){assert(0<=v&&v<g.size());selected[v]=true;}for(constauto&e:g.edges()){if(e.from==e.to)continue;if(!selected[e.from]&&!selected[e.to])returnfalse;}returntrue;}template<classT>MaximumCliqueResultmaximum_clique(constGraph<T>&g){autoadjacent=detail::undirected_adjacency_matrix(g);autocomplement=detail::complement_adjacency_matrix(adjacent);detail::MaximumIndependentSetBranchingsolver(complement);returnMaximumCliqueResult{solver.solve()};}template<classT>intmaximum_clique_size(constGraph<T>&g){returnmaximum_clique(g).size();}template<classT>MaximumIndependentSetResultmaximum_independent_set(constGraph<T>&g){autoadjacent=detail::undirected_adjacency_matrix(g);detail::MaximumIndependentSetBranchingsolver(adjacent);returnMaximumIndependentSetResult{solver.solve()};}template<classT>intmaximum_independent_set_size(constGraph<T>&g){returnmaximum_independent_set(g).size();}template<classT>MinimumVertexCoverResultminimum_vertex_cover(constGraph<T>&g){autoindependent=maximum_independent_set(g);std::vector<char>in_independent(g.size(),false);for(intv:independent.vertices)in_independent[v]=true;MinimumVertexCoverResultresult;for(intv=0;v<g.size();v++){if(!in_independent[v])result.vertices.push_back(v);}returnresult;}template<classT>intminimum_vertex_cover_size(constGraph<T>&g){returnminimum_vertex_cover(g).size();}}// namespace graph}// namespace m1une#line 1 "graph/minimum_steiner_tree.hpp"
#line 15 "graph/minimum_steiner_tree.hpp"
#line 17 "graph/minimum_steiner_tree.hpp"
namespacem1une{namespacegraph{template<classCost>structMinimumSteinerTreeResult{Costcost;std::vector<int>edge_ids;std::vector<int>vertices;};namespaceinternal{inlinestd::vector<int>steiner_terminals(intn,std::vector<int>terminals){for(intv:terminals)assert(0<=v&&v<n);std::sort(terminals.begin(),terminals.end());terminals.erase(std::unique(terminals.begin(),terminals.end()),terminals.end());assert(terminals.size()<std::numeric_limits<std::size_t>::digits);returnterminals;}template<classCost>structMinimumSteinerTreeDp{Costcost;Costinf;std::size_tstates;std::size_twidth;std::vector<Cost>dp;std::vector<int>terminals;};template<classCost,classGraphCost,classEdgeCost>std::optional<MinimumSteinerTreeDp<Cost>>minimum_steiner_tree_dp(constGraph<GraphCost>&g,std::vector<int>terminals,conststd::vector<Cost>&vertex_cost,EdgeCostedge_cost,Costinf){constintn=g.size();assert(vertex_cost.size()==std::size_t(n));for(Costcost:vertex_cost)assert(Cost(0)<=cost);terminals=steiner_terminals(n,std::move(terminals));constintk=int(terminals.size());if(k==0)returnMinimumSteinerTreeDp<Cost>{Cost(0),inf,1,std::size_t(n),{},{}};assert(Cost(0)<inf);for(intv=0;v<n;v++){for(constauto&edge:g[v]){if(edge.alive)assert(Cost(0)<=edge_cost(edge));}}conststd::size_tstates=std::size_t(1)<<k;conststd::size_twidth=std::size_t(n);assert(width<=std::numeric_limits<std::size_t>::max()/states);std::vector<Cost>dp(states*width,inf);for(inti=0;i<k;i++){constintterminal=terminals[i];if(vertex_cost[terminal]<inf){dp[(std::size_t(1)<<i)*width+std::size_t(terminal)]=vertex_cost[terminal];}}usingQueueEntry=std::pair<Cost,int>;for(std::size_tmask=1;mask<states;mask++){conststd::size_tmask_offset=mask*width;for(std::size_tsub=(mask-1)&mask;sub!=0;sub=(sub-1)&mask){conststd::size_tother=mask^sub;if(sub>other)continue;conststd::size_tsub_offset=sub*width;conststd::size_tother_offset=other*width;for(intv=0;v<n;v++){conststd::size_tvertex=std::size_t(v);constCostleft=dp[sub_offset+vertex];constCostright=dp[other_offset+vertex];if(left==inf||right==inf)continue;assert(vertex_cost[v]<=right);constCostextra=right-vertex_cost[v];if(left>inf-extra)continue;constCostcandidate=left+extra;Cost¤t=dp[mask_offset+vertex];if(candidate<current)current=candidate;}}std::priority_queue<QueueEntry,std::vector<QueueEntry>,std::greater<QueueEntry>>queue;for(intv=0;v<n;v++){constCostdistance=dp[mask_offset+std::size_t(v)];if(distance!=inf)queue.emplace(distance,v);}while(!queue.empty()){auto[distance,v]=queue.top();queue.pop();if(distance!=dp[mask_offset+std::size_t(v)])continue;for(constauto&edge:g[v]){if(!edge.alive)continue;constCostcost=edge_cost(edge);if(cost>=inf||vertex_cost[edge.to]>inf-cost)continue;constCostextra=cost+vertex_cost[edge.to];if(distance>inf-extra)continue;constCostcandidate=distance+extra;Cost¤t=dp[mask_offset+std::size_t(edge.to)];if(current<=candidate)continue;current=candidate;queue.emplace(candidate,edge.to);}}}constautoanswer_begin=dp.begin()+(states-1)*width;constCostanswer=*std::min_element(answer_begin,dp.end());if(answer==inf)returnstd::nullopt;returnMinimumSteinerTreeDp<Cost>{answer,inf,states,width,std::move(dp),std::move(terminals)};}template<classT>std::optional<MinimumSteinerTreeDp<int>>minimum_steiner_tree_unweighted_dp(constGraph<T>&g,std::vector<int>terminals){constintn=g.size();terminals=steiner_terminals(n,std::move(terminals));constintk=int(terminals.size());if(k==0)returnMinimumSteinerTreeDp<int>{0,n,1,std::size_t(n),{},{}};conststd::size_tstates=std::size_t(1)<<k;conststd::size_twidth=std::size_t(n);assert(width<=std::numeric_limits<std::size_t>::max()/states);constintinf=n;std::vector<int>dp(states*width,inf);for(inti=0;i<k;i++){dp[(std::size_t(1)<<i)*width+std::size_t(terminals[i])]=0;}for(std::size_tmask=1;mask<states;mask++){conststd::size_tmask_offset=mask*width;for(std::size_tsub=(mask-1)&mask;sub!=0;sub=(sub-1)&mask){conststd::size_tother=mask^sub;if(sub>other)continue;conststd::size_tsub_offset=sub*width;conststd::size_tother_offset=other*width;for(intv=0;v<n;v++){conststd::size_tvertex=std::size_t(v);constintcandidate=dp[sub_offset+vertex]+dp[other_offset+vertex];int¤t=dp[mask_offset+vertex];if(candidate<current)current=candidate;}}std::vector<int>bucket_head(n,-1);std::vector<int>entry_vertex;std::vector<int>entry_next;entry_vertex.reserve(2*width);entry_next.reserve(2*width);autopush=[&](intdistance,intv){entry_vertex.push_back(v);entry_next.push_back(bucket_head[distance]);bucket_head[distance]=int(entry_vertex.size())-1;};for(intv=0;v<n;v++){constintdistance=dp[mask_offset+std::size_t(v)];if(distance!=inf)push(distance,v);}for(intdistance=0;distance<n;distance++){for(intentry=bucket_head[distance];entry!=-1;entry=entry_next[entry]){constintv=entry_vertex[entry];if(dp[mask_offset+std::size_t(v)]!=distance)continue;for(constauto&edge:g[v]){if(!edge.alive)continue;int¤t=dp[mask_offset+std::size_t(edge.to)];if(distance+1>=current)continue;current=distance+1;push(current,edge.to);}}}}constautoanswer_begin=dp.begin()+(states-1)*width;constintanswer=*std::min_element(answer_begin,dp.end());if(answer==inf)returnstd::nullopt;returnMinimumSteinerTreeDp<int>{answer,inf,states,width,std::move(dp),std::move(terminals)};}template<classCost,classGraphCost,classEdgeCost>MinimumSteinerTreeResult<Cost>restore_minimum_steiner_tree(constGraph<GraphCost>&g,constMinimumSteinerTreeDp<Cost>&data,conststd::vector<Cost>&vertex_cost,EdgeCostedge_cost){MinimumSteinerTreeResult<Cost>result;result.cost=data.cost;if(data.terminals.empty())returnresult;constintn=g.size();conststd::size_tcells=data.states*data.width;std::vector<char>state(cells,0);std::vector<char>selected_edge(g.edge_count(),false);std::function<bool(std::size_t,int)>restore=[&](std::size_tmask,intstart){conststd::size_tposition=mask*data.width+std::size_t(start);if(state[position]==2)returntrue;if(state[position]==1)returnfalse;state[position]=1;std::vector<int>search_parent(n,-2),search_edge(n,-1),stack;search_parent[start]=-1;stack.push_back(start);intseed=-1;std::size_tseed_split=0;while(!stack.empty()&&seed==-1){constintv=stack.back();stack.pop_back();conststd::size_tvertex_position=mask*data.width+std::size_t(v);constCostcurrent=data.dp[vertex_position];if(v!=start&&state[vertex_position]==2){seed=v;break;}if((mask&(mask-1))==0){constintterminal_index=int(std::countr_zero(mask));if(v==data.terminals[terminal_index]&¤t==vertex_cost[v]){seed=v;break;}}for(std::size_tsub=(mask-1)&mask;sub!=0;sub=(sub-1)&mask){conststd::size_tother=mask^sub;if(sub>other)continue;constCostleft=data.dp[sub*data.width+std::size_t(v)];constCostright=data.dp[other*data.width+std::size_t(v)];if(left==data.inf||right==data.inf||right<vertex_cost[v])continue;constCostextra=right-vertex_cost[v];if(left>data.inf-extra||left+extra!=current)continue;seed=v;seed_split=sub;break;}if(seed!=-1)break;for(constauto&edge:g[v]){if(!edge.alive||search_parent[edge.to]!=-2)continue;constCostcost=edge_cost(edge);if(cost>=data.inf||vertex_cost[v]>data.inf-cost)continue;constCostextra=cost+vertex_cost[v];constCostprevious=data.dp[mask*data.width+std::size_t(edge.to)];if(previous==data.inf||previous>data.inf-extra)continue;if(previous+extra!=current)continue;search_parent[edge.to]=v;search_edge[edge.to]=edge.id;stack.push_back(edge.to);}}if(seed==-1){state[position]=0;returnfalse;}if(seed_split!=0){constboolrestored_left=restore(seed_split,seed);constboolrestored_right=restore(mask^seed_split,seed);assert(restored_left&&restored_right);if(!restored_left||!restored_right){state[position]=0;returnfalse;}}for(intv=seed;v!=-1;v=search_parent[v]){state[mask*data.width+std::size_t(v)]=2;if(search_parent[v]==-1)continue;constintid=search_edge[v];assert(0<=id&&id<g.edge_count());selected_edge[id]=true;}returntrue;};introot=-1;conststd::size_tfull_mask=data.states-1;for(intv=0;v<n;v++){if(data.dp[full_mask*data.width+std::size_t(v)]==data.cost){root=v;break;}}assert(root!=-1);constboolrestored=restore(full_mask,root);assert(restored);(void)restored;std::vector<Edge<GraphCost>>edge_by_id(g.edge_count());std::vector<char>has_edge(g.edge_count(),false);for(constauto&edge:g.edges()){edge_by_id[edge.id]=edge;has_edge[edge.id]=true;}std::vector<int>parent(n),component_size(n,1);for(intv=0;v<n;v++)parent[v]=v;autoleader=[&](auto&&self,intv)->int{if(parent[v]==v)returnv;returnparent[v]=self(self,parent[v]);};std::vector<char>tree_edge(g.edge_count(),false);for(intid=0;id<g.edge_count();id++){if(!selected_edge[id])continue;assert(has_edge[id]);constauto&edge=edge_by_id[id];intu=leader(leader,edge.from);intv=leader(leader,edge.to);if(u==v)continue;if(component_size[u]<component_size[v])std::swap(u,v);parent[v]=u;component_size[u]+=component_size[v];tree_edge[id]=true;}std::vector<std::vector<std::pair<int,int>>>tree(n);std::vector<int>degree(n,0);std::vector<char>in_tree(n,false),is_terminal(n,false);for(intterminal:data.terminals){in_tree[terminal]=true;is_terminal[terminal]=true;}for(intid=0;id<g.edge_count();id++){if(!tree_edge[id])continue;constauto&edge=edge_by_id[id];tree[edge.from].emplace_back(edge.to,id);tree[edge.to].emplace_back(edge.from,id);degree[edge.from]++;degree[edge.to]++;in_tree[edge.from]=true;in_tree[edge.to]=true;}std::queue<int>leaves;for(intv=0;v<n;v++){if(in_tree[v]&&!is_terminal[v]&°ree[v]<=1)leaves.push(v);}std::vector<char>removed_vertex(n,false),removed_edge(g.edge_count(),false);while(!leaves.empty()){constintv=leaves.front();leaves.pop();if(removed_vertex[v]||is_terminal[v]||degree[v]>1)continue;removed_vertex[v]=true;for(auto[to,id]:tree[v]){if(removed_edge[id])continue;removed_edge[id]=true;degree[v]--;degree[to]--;if(!is_terminal[to]&°ree[to]<=1)leaves.push(to);break;}}Costrestored_cost=Cost(0);for(intid=0;id<g.edge_count();id++){if(!tree_edge[id]||removed_edge[id])continue;result.edge_ids.push_back(id);restored_cost+=edge_cost(edge_by_id[id]);}for(intv=0;v<n;v++){if(!in_tree[v]||removed_vertex[v])continue;result.vertices.push_back(v);restored_cost+=vertex_cost[v];}ifconstexpr(std::is_integral_v<Cost>)assert(restored_cost==result.cost);result.cost=restored_cost;returnresult;}}// namespace internaltemplate<classT>std::optional<T>minimum_steiner_tree(constGraph<T>&g,std::vector<int>terminals,conststd::vector<T>&vertex_cost,Tinf=std::numeric_limits<T>::max()/T(4)){autoresult=internal::minimum_steiner_tree_dp(g,std::move(terminals),vertex_cost,[](constEdge<T>&edge){returnedge.cost;},inf);if(!result)returnstd::nullopt;returnresult->cost;}template<classT>std::optional<T>minimum_steiner_tree(constGraph<T>&g,std::vector<int>terminals,Tinf=std::numeric_limits<T>::max()/T(4)){returnminimum_steiner_tree(g,std::move(terminals),std::vector<T>(g.size(),T(0)),inf);}template<classGraphCost,classCost>std::optional<Cost>minimum_steiner_tree_unweighted(constGraph<GraphCost>&g,std::vector<int>terminals,conststd::vector<Cost>&vertex_cost,Costinf=std::numeric_limits<Cost>::max()/Cost(4)){autoresult=internal::minimum_steiner_tree_dp(g,std::move(terminals),vertex_cost,[](constEdge<GraphCost>&){returnCost(1);},inf);if(!result)returnstd::nullopt;returnresult->cost;}template<classT>std::optional<MinimumSteinerTreeResult<T>>build_minimum_steiner_tree(constGraph<T>&g,std::vector<int>terminals,conststd::vector<T>&vertex_cost,Tinf=std::numeric_limits<T>::max()/T(4)){autodata=internal::minimum_steiner_tree_dp(g,std::move(terminals),vertex_cost,[](constEdge<T>&edge){returnedge.cost;},inf);if(!data)returnstd::nullopt;returninternal::restore_minimum_steiner_tree(g,*data,vertex_cost,[](constEdge<T>&edge){returnedge.cost;});}template<classT>std::optional<MinimumSteinerTreeResult<T>>build_minimum_steiner_tree(constGraph<T>&g,std::vector<int>terminals,Tinf=std::numeric_limits<T>::max()/T(4)){std::vector<T>vertex_cost(g.size(),T(0));returnbuild_minimum_steiner_tree(g,std::move(terminals),vertex_cost,inf);}template<classGraphCost,classCost>std::optional<MinimumSteinerTreeResult<Cost>>build_minimum_steiner_tree_unweighted(constGraph<GraphCost>&g,std::vector<int>terminals,conststd::vector<Cost>&vertex_cost,Costinf=std::numeric_limits<Cost>::max()/Cost(4)){autodata=internal::minimum_steiner_tree_dp(g,std::move(terminals),vertex_cost,[](constEdge<GraphCost>&){returnCost(1);},inf);if(!data)returnstd::nullopt;returninternal::restore_minimum_steiner_tree(g,*data,vertex_cost,[](constEdge<GraphCost>&){returnCost(1);});}template<classT>std::optional<MinimumSteinerTreeResult<int>>build_minimum_steiner_tree_unweighted(constGraph<T>&g,std::vector<int>terminals){autodata=internal::minimum_steiner_tree_unweighted_dp(g,std::move(terminals));if(!data)returnstd::nullopt;std::vector<int>vertex_cost(g.size(),0);returninternal::restore_minimum_steiner_tree(g,*data,vertex_cost,[](constEdge<T>&){return1;});}template<classT>std::optional<int>minimum_steiner_tree_unweighted(constGraph<T>&g,std::vector<int>terminals){autoresult=internal::minimum_steiner_tree_unweighted_dp(g,std::move(terminals));if(!result)returnstd::nullopt;returnresult->cost;}}// namespace graph}// namespace m1une#line 1 "graph/namori.hpp"
#line 9 "graph/namori.hpp"
#line 11 "graph/namori.hpp"
namespacem1une{namespacegraph{template<classT>structNamoriDecomposition{intcomponent_count;std::vector<std::vector<int>>cycles;std::vector<std::vector<int>>cycle_edge_ids;std::vector<std::vector<T>>cycle_edge_costs;std::vector<bool>on_cycle;std::vector<int>component;std::vector<int>cycle_root;std::vector<int>cycle_position;std::vector<int>parent;std::vector<int>parent_edge;std::vector<int>depth;std::vector<T>dist_to_cycle;std::vector<std::vector<int>>children;boolsame_component(intu,intv)const{assert(0<=u&&u<int(component.size()));assert(0<=v&&v<int(component.size()));returncomponent[u]==component[v];}boolsame_tree(intu,intv)const{assert(0<=u&&u<int(cycle_root.size()));assert(0<=v&&v<int(cycle_root.size()));returncycle_root[u]==cycle_root[v];}};template<classT>std::optional<NamoriDecomposition<T>>namori_decomposition(constGraph<T>&graph){intn=graph.size();NamoriDecomposition<T>result;result.component_count=0;result.on_cycle.assign(n,false);result.component.assign(n,-1);result.cycle_root.assign(n,-1);result.cycle_position.assign(n,-1);result.parent.assign(n,-1);result.parent_edge.assign(n,-1);result.depth.assign(n,0);result.dist_to_cycle.assign(n,T(0));result.children.assign(n,{});if(n==0)returnresult;std::vector<int>degree(n,0);for(intv=0;v<n;v++){for(constauto&edge:graph[v]){if(edge.alive)degree[v]++;}}std::queue<int>queue;std::vector<bool>removed(n,false);for(intv=0;v<n;v++){if(degree[v]<=1)queue.push(v);}while(!queue.empty()){intv=queue.front();queue.pop();if(removed[v]||degree[v]>1)continue;removed[v]=true;for(constauto&edge:graph[v]){if(!edge.alive||removed[edge.to])continue;degree[edge.to]--;if(degree[edge.to]==1)queue.push(edge.to);}}for(intv=0;v<n;v++){result.on_cycle[v]=!removed[v];}for(intv=0;v<n;v++){if(!result.on_cycle[v])continue;intcycle_degree=0;for(constauto&edge:graph[v]){if(edge.alive&&result.on_cycle[edge.to])cycle_degree++;}if(cycle_degree!=2)returnstd::nullopt;}std::vector<bool>cycle_visited(n,false);for(intstart=0;start<n;start++){if(!result.on_cycle[start]||cycle_visited[start])continue;intcomponent_id=int(result.cycles.size());std::vector<int>vertices;std::vector<int>edge_ids;std::vector<T>edge_costs;intcurrent=start;intprevious_edge=-1;while(true){if(cycle_visited[current])returnstd::nullopt;cycle_visited[current]=true;vertices.push_back(current);intnext_vertex=-1;intnext_edge=-1;Tnext_cost=T(0);for(constauto&edge:graph[current]){if(!edge.alive||!result.on_cycle[edge.to]||edge.id==previous_edge)continue;next_vertex=edge.to;next_edge=edge.id;next_cost=edge.cost;break;}if(next_edge==-1)returnstd::nullopt;edge_ids.push_back(next_edge);edge_costs.push_back(next_cost);if(next_vertex==start)break;previous_edge=next_edge;current=next_vertex;if(int(vertices.size())>n)returnstd::nullopt;}for(intposition=0;position<int(vertices.size());position++){intv=vertices[position];result.component[v]=component_id;result.cycle_root[v]=v;result.cycle_position[v]=position;}result.cycles.push_back(std::move(vertices));result.cycle_edge_ids.push_back(std::move(edge_ids));result.cycle_edge_costs.push_back(std::move(edge_costs));}if(result.cycles.empty())returnstd::nullopt;std::vector<int>stack;stack.reserve(n);for(constauto&cycle:result.cycles){for(intv:cycle)stack.push_back(v);}while(!stack.empty()){intv=stack.back();stack.pop_back();for(constauto&edge:graph[v]){if(!edge.alive||result.on_cycle[edge.to]||edge.id==result.parent_edge[v])continue;intto=edge.to;if(result.component[to]!=-1)continue;result.component[to]=result.component[v];result.cycle_root[to]=result.cycle_root[v];result.cycle_position[to]=result.cycle_position[v];result.parent[to]=v;result.parent_edge[to]=edge.id;result.depth[to]=result.depth[v]+1;result.dist_to_cycle[to]=result.dist_to_cycle[v]+edge.cost;result.children[v].push_back(to);stack.push_back(to);}}for(intv=0;v<n;v++){if(result.component[v]==-1)returnstd::nullopt;}result.component_count=int(result.cycles.size());returnresult;}template<classT>std::optional<NamoriDecomposition<T>>decompose_namori(constGraph<T>&graph){returnnamori_decomposition(graph);}}// namespace graph}// namespace m1une#line 1 "graph/st_numbering.hpp"
#line 6 "graph/st_numbering.hpp"
#line 8 "graph/st_numbering.hpp"
namespacem1une{namespacegraph{// Returns ranks p with p[source] = 0 and p[sink] = n - 1 such that every// other vertex has neighbors of both smaller and larger rank. Returns an empty// vector when no such numbering exists.template<classT>std::vector<int>st_numbering(constGraph<T>&graph,intsource,intsink){constintn=graph.size();assert(0<n);assert(0<=source&&source<n);assert(0<=sink&&sink<n);assert(source!=sink);#ifndef NDEBUG
std::vector<int>incidence_count(graph.edge_count(),0);for(intvertex=0;vertex<n;vertex++){for(constEdge<T>&edge:graph[vertex]){if(!edge.alive)continue;assert(0<=edge.id&&edge.id<graph.edge_count());incidence_count[edge.id]++;}}for(intedge_id=0;edge_id<graph.edge_count();edge_id++){if(graph.is_edge_alive(edge_id)){assert(incidence_count[edge_id]==2);}}#endif
std::vector<int>parent(n,-1);std::vector<int>preorder(n,-1);std::vector<int>low_vertex(n,-1);std::vector<int>next_edge(n,0);std::vector<int>traversal;traversal.reserve(n);preorder[source]=0;low_vertex[source]=source;traversal.push_back(source);preorder[sink]=1;low_vertex[sink]=sink;traversal.push_back(sink);std::vector<int>stack(1,sink);while(!stack.empty()){constintvertex=stack.back();if(next_edge[vertex]<int(graph[vertex].size())){constEdge<T>&edge=graph[vertex][next_edge[vertex]++];if(!edge.alive||edge.to==vertex)continue;constintto=edge.to;if(preorder[to]==-1){parent[to]=vertex;preorder[to]=int(traversal.size());low_vertex[to]=to;traversal.push_back(to);stack.push_back(to);}elseif(preorder[to]<preorder[low_vertex[vertex]]){low_vertex[vertex]=to;}continue;}stack.pop_back();constintparent_vertex=parent[vertex];if(parent_vertex!=-1&&preorder[low_vertex[vertex]]<preorder[low_vertex[parent_vertex]]){low_vertex[parent_vertex]=low_vertex[vertex];}}if(int(traversal.size())!=n)return{};std::vector<int>next(n,-1);std::vector<int>previous(n,-1);std::vector<int>sign(n,0);next[source]=sink;previous[sink]=source;sign[source]=-1;for(intindex=2;index<n;index++){constintvertex=traversal[index];constintparent_vertex=parent[vertex];assert(parent_vertex!=-1);if(sign[low_vertex[vertex]]==-1){constintbefore=previous[parent_vertex];if(before==-1)return{};next[before]=vertex;next[vertex]=parent_vertex;previous[vertex]=before;previous[parent_vertex]=vertex;sign[parent_vertex]=1;}else{constintafter=next[parent_vertex];if(after==-1)return{};next[parent_vertex]=vertex;next[vertex]=after;previous[vertex]=parent_vertex;previous[after]=vertex;sign[parent_vertex]=-1;}}std::vector<int>order;order.reserve(n);intvertex=source;while(vertex!=-1&&int(order.size())<=n){order.push_back(vertex);if(vertex==sink)break;vertex=next[vertex];}if(int(order.size())!=n||order.back()!=sink)return{};std::vector<int>rank(n,-1);for(intindex=0;index<n;index++)rank[order[index]]=index;for(intindex=0;index<n;index++){constintcurrent=order[index];boolhas_smaller=false;boolhas_larger=false;for(constEdge<T>&edge:graph[current]){if(!edge.alive||edge.to==current)continue;has_smaller=has_smaller||rank[edge.to]<index;has_larger=has_larger||index<rank[edge.to];}if(index>0&&!has_smaller)return{};if(index+1<n&&!has_larger)return{};}returnrank;}}// namespace graph}// namespace m1une#line 1 "graph/three_edge_connected_components.hpp"
#line 9 "graph/three_edge_connected_components.hpp"
#line 11 "graph/three_edge_connected_components.hpp"
namespacem1une{namespacegraph{structThreeEdgeConnectedComponentsResult{std::vector<std::vector<int>>components;std::vector<int>component_of_vertex;intcomponent_count()const{returnint(components.size());}boolsame(intfirst,intsecond)const{assert(0<=first&&first<int(component_of_vertex.size()));assert(0<=second&&second<int(component_of_vertex.size()));returncomponent_of_vertex[first]==component_of_vertex[second];}};namespaceinternal{// Maintains every component as a circular linked list. Swapping two successors// concatenates two different lists in O(1) time.structThreeEdgeComponentCycles{std::vector<int>next;explicitThreeEdgeComponentCycles(intn):next(n){std::iota(next.begin(),next.end(),0);}voidunite(intfirst,intsecond){std::swap(next[first],next[second]);}ThreeEdgeConnectedComponentsResultbuild_result()const{constintn=int(next.size());ThreeEdgeConnectedComponentsResultresult;result.component_of_vertex.assign(n,-1);for(intfirst=0;first<n;first++){if(result.component_of_vertex[first]!=-1)continue;constintcomponent=result.component_count();result.components.emplace_back();intvertex=first;do{result.component_of_vertex[vertex]=component;result.components.back().push_back(vertex);vertex=next[vertex];}while(vertex!=first);}returnresult;}};}// namespace internal// Decomposes an undirected multigraph into maximal vertex sets joined by at// least three edge-disjoint paths. This is an iterative form of Tsin's// one-pass contraction algorithm.template<classT>ThreeEdgeConnectedComponentsResultthree_edge_connected_components(constGraph<T>&graph){constintn=graph.size();constintedge_count=graph.edge_count();#ifndef NDEBUG
std::vector<int>incidence_count(edge_count,0);for(intvertex=0;vertex<n;vertex++){for(constEdge<T>&edge:graph[vertex]){if(!edge.alive)continue;assert(edge.from==vertex);assert(0<=edge.to&&edge.to<n);assert(0<=edge.id&&edge.id<edge_count);incidence_count[edge.id]++;}}for(intedge_id=0;edge_id<edge_count;edge_id++){if(incidence_count[edge_id]!=0)assert(incidence_count[edge_id]==2);}#endif
constintnone=n;std::vector<int>enter(n,-1);std::vector<int>leave(n,0);std::vector<int>low(n,none);std::vector<int>degree(n,0);std::vector<int>path(n,none);std::vector<int>parent(n,-1);std::vector<int>parent_edge(n,-1);std::vector<int>next_edge(n,0);std::vector<int>dfs_stack;internal::ThreeEdgeComponentCyclescomponent_cycles(n);inttimer=0;autoabsorb=[&](intvertex,intother){component_cycles.unite(vertex,other);degree[vertex]+=degree[other];};autoprocess_visited_edge=[&](intvertex,intto){if(enter[to]<enter[vertex]){degree[vertex]++;low[vertex]=std::min(low[vertex],enter[to]);return;}degree[vertex]--;intcurrent=path[vertex];while(current!=none&&enter[current]<=enter[to]&&enter[to]<leave[current]){absorb(vertex,current);current=path[current];}path[vertex]=current;};autoprocess_child=[&](intvertex,intchild){if(path[child]==none&°ree[child]<=1){degree[vertex]+=degree[child];low[vertex]=std::min(low[vertex],low[child]);return;}intcurrent=child;if(degree[child]==0)current=path[child];assert(current!=none);if(low[current]<low[vertex]){low[vertex]=low[current];std::swap(current,path[vertex]);}while(current!=none){absorb(vertex,current);current=path[current];}};for(introot=0;root<n;root++){if(enter[root]!=-1)continue;enter[root]=timer++;dfs_stack.push_back(root);while(!dfs_stack.empty()){constintvertex=dfs_stack.back();if(next_edge[vertex]<int(graph[vertex].size())){constEdge<T>&edge=graph[vertex][next_edge[vertex]++];if(!edge.alive||edge.from==edge.to||edge.id==parent_edge[vertex])continue;constintto=edge.to;if(enter[to]==-1){parent[to]=vertex;parent_edge[to]=edge.id;enter[to]=timer++;dfs_stack.push_back(to);}else{process_visited_edge(vertex,to);}continue;}leave[vertex]=timer;dfs_stack.pop_back();if(parent[vertex]!=-1)process_child(parent[vertex],vertex);}}returncomponent_cycles.build_result();}}// namespace graph}// namespace m1une#line 1 "graph/two_edge_connected_components.hpp"
#line 6 "graph/two_edge_connected_components.hpp"
#line 8 "graph/two_edge_connected_components.hpp"
namespacem1une{namespacegraph{structTwoEdgeConnectedBridge{intfrom;intto;intedge_id;};structTwoEdgeConnectedComponentsResult{std::vector<std::vector<int>>components;std::vector<int>component_of_vertex;std::vector<int>bridge_ids;std::vector<char>bridge;std::vector<TwoEdgeConnectedBridge>bridge_forest_edges;std::vector<int>ord;std::vector<int>low;intcomponent_count()const{returnint(components.size());}boolsame(intfirst,intsecond)const{assert(0<=first&&first<int(component_of_vertex.size()));assert(0<=second&&second<int(component_of_vertex.size()));returncomponent_of_vertex[first]==component_of_vertex[second];}boolis_bridge(intedge_id)const{assert(0<=edge_id&&edge_id<int(bridge.size()));returnbridge[edge_id];}};// Removes every active bridge and returns the remaining connected components.// The first lowlink traversal and the component traversal are both iterative.template<classT>TwoEdgeConnectedComponentsResulttwo_edge_connected_components(constGraph<T>&graph){constintn=graph.size();constintedge_count=graph.edge_count();TwoEdgeConnectedComponentsResultresult;result.component_of_vertex.assign(n,-1);result.bridge.assign(edge_count,false);result.ord.assign(n,-1);result.low.assign(n,-1);std::vector<int>edge_from(edge_count,-1);std::vector<int>edge_to(edge_count,-1);std::vector<int>incidence_count(edge_count,0);for(intvertex=0;vertex<n;vertex++){for(constEdge<T>&edge:graph[vertex]){if(!edge.alive)continue;assert(0<=edge.id&&edge.id<edge_count);if(incidence_count[edge.id]==0){edge_from[edge.id]=edge.from;edge_to[edge.id]=edge.to;}incidence_count[edge.id]++;}}#ifndef NDEBUG
for(intedge_id=0;edge_id<edge_count;edge_id++){if(incidence_count[edge_id]!=0)assert(incidence_count[edge_id]==2);}#endif
std::vector<int>parent(n,-1);std::vector<int>parent_edge(n,-1);std::vector<int>next_edge(n,0);std::vector<int>stack;inttimer=0;for(introot=0;root<n;root++){if(result.ord[root]!=-1)continue;result.ord[root]=result.low[root]=timer++;stack.push_back(root);while(!stack.empty()){constintvertex=stack.back();if(next_edge[vertex]<int(graph[vertex].size())){constEdge<T>&edge=graph[vertex][next_edge[vertex]++];if(!edge.alive||edge.id==parent_edge[vertex])continue;constintto=edge.to;if(result.ord[to]==-1){parent[to]=vertex;parent_edge[to]=edge.id;result.ord[to]=result.low[to]=timer++;stack.push_back(to);}elseif(result.ord[to]<result.low[vertex]){result.low[vertex]=result.ord[to];}continue;}stack.pop_back();constintparent_vertex=parent[vertex];if(parent_vertex==-1)continue;if(result.low[vertex]<result.low[parent_vertex]){result.low[parent_vertex]=result.low[vertex];}if(result.ord[parent_vertex]<result.low[vertex]){result.bridge[parent_edge[vertex]]=true;}}}for(introot=0;root<n;root++){if(result.component_of_vertex[root]!=-1)continue;constintcomponent=result.component_count();result.components.emplace_back();result.component_of_vertex[root]=component;stack.push_back(root);while(!stack.empty()){constintvertex=stack.back();stack.pop_back();result.components.back().push_back(vertex);for(constEdge<T>&edge:graph[vertex]){if(!edge.alive||result.bridge[edge.id])continue;if(result.component_of_vertex[edge.to]!=-1)continue;result.component_of_vertex[edge.to]=component;stack.push_back(edge.to);}}}for(intedge_id=0;edge_id<edge_count;edge_id++){if(!result.bridge[edge_id])continue;result.bridge_ids.push_back(edge_id);constintfirst_component=result.component_of_vertex[edge_from[edge_id]];constintsecond_component=result.component_of_vertex[edge_to[edge_id]];assert(first_component!=second_component);result.bridge_forest_edges.push_back(TwoEdgeConnectedBridge{first_component,second_component,edge_id});}returnresult;}}// namespace graph}// namespace m1une#line 32 "graph/undirected.hpp"
#line 15 "graph/all.hpp"
#line 11 "verify/graph/graph_algorithms.test.cpp"
usingm1une::graph::Graph;voidtest_graph_container(){Graph<int>g(2);assert(g.size()==2);intadded=g.add_vertex();assert(added==2);inte0=g.add_directed_edge(0,1,4);inte1=g.add_edge(1,2,5);assert(e0==0);assert(e1==1);assert(g.edge_count()==2);assert(g[1].size()==1);assert(g.edges().size()==2);autorev=g.reversed();assert(rev[1][0].to==0);}voidtest_edge_alive(){Graph<int>g(4);inte01=g.add_edge(0,1);inte12=g.add_edge(1,2);inte23=g.add_edge(2,3);(void)e01;(void)e23;assert(g.edge_count()==3);assert(g.edges().size()==3);autores=m1une::graph::bfs(g,0);assert(res.dist[3]==3);g.erase_edge(e12);assert(!g.is_edge_alive(e12));assert(g.edges().size()==2);assert(g.edges(true).size()==3);autocut=m1une::graph::bfs(g,0);assert(!cut.reachable(3));autorev=g.reversed();assert(!rev.is_edge_alive(e12));assert(rev.edges().size()==2);g.revive_edge(e12);assert(g.is_edge_alive(e12));autorestored=m1une::graph::bfs(g,0);assert(restored.dist[3]==3);}voidtest_bfs(){Graph<int>g(5);g.add_directed_edge(0,1);g.add_directed_edge(0,2);g.add_directed_edge(1,3);g.add_directed_edge(2,3);g.add_directed_edge(3,4);autores=m1une::graph::bfs(g,0);assert(res.dist[0]==0);assert(res.dist[3]==2);assert(res.dist[4]==3);autopath=res.path(4);assert(path.front()==0);assert(path.back()==4);assert(path.size()==4);}voidtest_dijkstra(){Graph<longlong>g(5);g.add_directed_edge(0,1,4);g.add_directed_edge(0,2,1);g.add_directed_edge(2,1,2);g.add_directed_edge(1,3,1);g.add_directed_edge(2,3,7);g.add_directed_edge(3,4,3);autores=m1une::graph::dijkstra(g,0);assert(res.dist[1]==3);assert(res.dist[4]==7);assert((res.path(4)==std::vector<int>{0,2,1,3,4}));}voidtest_zero_one_bfs(){Graph<int>g(6);g.add_directed_edge(0,1,1);g.add_directed_edge(0,2,0);g.add_directed_edge(2,1,0);g.add_directed_edge(1,3,1);g.add_directed_edge(2,3,1);g.add_directed_edge(3,4,0);autores=m1une::graph::zero_one_bfs(g,0);assert(res.dist[0]==0);assert(res.dist[1]==0);assert(res.dist[3]==1);assert(res.dist[4]==1);assert(!res.reachable(5));assert((res.path(4)==std::vector<int>{0,2,3,4}));automulti=m1une::graph::zero_one_bfs(g,std::vector<int>{1,5});assert(multi.dist[1]==0);assert(multi.dist[4]==1);assert(multi.dist[5]==0);}voidtest_bellman_ford(){Graph<longlong>g(5);g.add_directed_edge(0,1,1);g.add_directed_edge(1,2,-3);g.add_directed_edge(2,3,1);g.add_directed_edge(3,1,1);g.add_directed_edge(0,4,5);autores=m1une::graph::bellman_ford(g,0);assert(res.has_negative_cycle);assert(res.affected_by_negative_cycle(1));assert(res.affected_by_negative_cycle(2));assert(res.affected_by_negative_cycle(3));assert(!res.affected_by_negative_cycle(4));assert(res.dist[4]==5);}voidtest_dag_shortest_path(){Graph<longlong>g(6);g.add_directed_edge(0,1,2);g.add_directed_edge(0,2,5);g.add_directed_edge(1,2,-4);g.add_directed_edge(1,4,10);g.add_directed_edge(2,3,3);g.add_directed_edge(3,4,1);autores=m1une::graph::dag_shortest_path(g,0);assert(res.has_value());assert(res->dist[0]==0);assert(res->dist[2]==-2);assert(res->dist[4]==2);assert(!res->reachable(5));assert((res->path(4)==std::vector<int>{0,1,2,3,4}));assert(res->topological_order.size()==6);automulti=m1une::graph::dag_shortest_path(g,std::vector<int>{1,5});assert(multi.has_value());assert(multi->dist[4]==0);assert(multi->dist[5]==0);g.add_directed_edge(4,1,1);autocyclic=m1une::graph::dag_shortest_path(g,0);assert(!cyclic.has_value());}voidtest_warshall_floyd(){Graph<longlong>g(4);g.add_directed_edge(0,1,3);g.add_directed_edge(1,2,4);g.add_directed_edge(0,2,10);g.add_directed_edge(2,3,-2);autodist=m1une::graph::warshall_floyd(g);assert(dist[0][2]==7);assert(dist[0][3]==5);assert(!m1une::graph::has_negative_cycle(dist));boolchanged=m1une::graph::warshall_floyd_add_directed_edge(dist,3,1,1LL);assert(changed);assert(dist[0][1]==3);assert(dist[2][1]==-1);assert(dist[3][2]==5);changed=m1une::graph::warshall_floyd_add_directed_edge(dist,0,2,100LL);assert(!changed);Graph<longlong>undirected(4);undirected.add_edge(0,1,10);undirected.add_edge(1,2,10);undirected.add_edge(2,3,10);autoudist=m1une::graph::warshall_floyd(undirected);changed=m1une::graph::warshall_floyd_add_undirected_edge(udist,0,3,1LL);assert(changed);assert(udist[0][3]==1);assert(udist[3][0]==1);assert(udist[1][3]==11);}voidtest_topological_sort(){Graph<int>g(4);g.add_directed_edge(0,1);g.add_directed_edge(0,2);g.add_directed_edge(1,3);g.add_directed_edge(2,3);autoorder=m1une::graph::topological_sort(g);assert(order.has_value());std::vector<int>pos(4);for(inti=0;i<4;i++)pos[(*order)[i]]=i;for(intv=0;v<4;v++){for(constauto&e:g[v])assert(pos[e.from]<pos[e.to]);}g.add_directed_edge(3,0);assert(!m1une::graph::is_dag(g));}voidtest_scc(){Graph<int>g(4);g.add_directed_edge(0,1);g.add_directed_edge(1,0);g.add_directed_edge(1,2);g.add_directed_edge(2,3);g.add_directed_edge(3,2);autoscc=m1une::graph::strongly_connected_components(g);assert(scc.count==2);assert(scc.same(0,1));assert(scc.same(2,3));assert(!scc.same(0,2));autodag=scc.dag(g);assert(dag.size()==2);assert(dag.edge_count()==1);}voidtest_lowlink(){Graph<int>g(5);g.add_edge(0,1);g.add_edge(1,2);g.add_edge(2,0);intb0=g.add_edge(1,3);intb1=g.add_edge(3,4);autores=m1une::graph::lowlink(g);assert((res.articulation==std::vector<int>{1,3}));assert((res.bridge_ids==std::vector<int>{b0,b1}));}voidtest_bipartite_and_components(){Graph<int>square(4);square.add_edge(0,1);square.add_edge(1,2);square.add_edge(2,3);square.add_edge(3,0);autobp=m1une::graph::bipartite(square);assert(bp.is_bipartite);assert(bp.color[0]==bp.color[2]);assert((bp.left_vertices==std::vector<int>{0,2}));assert((bp.right_vertices==std::vector<int>{1,3}));assert(bp.left_id[2]==1);assert(bp.right_id[3]==1);autobuilt=m1une::graph::make_bipartite_matching(square);assert(built.has_value());assert(built->matching.left_size()==2);assert(built->matching.right_size()==2);assert(built->matching.max_matching()==2);for(constauto&p:built->matching.matching()){intu=built->left_vertex(p.left);intv=built->right_vertex(p.right);assert(bp.color[u]==0);assert(bp.color[v]==1);assert(square.is_edge_alive(built->original_edge(p.edge_id)));}Graph<int>triangle(3);triangle.add_edge(0,1);triangle.add_edge(1,2);triangle.add_edge(2,0);assert(!m1une::graph::is_bipartite(triangle));assert(!m1une::graph::make_bipartite_matching(triangle).has_value());Graph<int>cc_graph(5);cc_graph.add_edge(0,1);cc_graph.add_edge(2,3);autocc=m1une::graph::connected_components(cc_graph);assert(cc.count==3);assert(cc.same(0,1));assert(cc.same(2,3));assert(!cc.same(0,2));Graph<int>directed(2);directed.add_directed_edge(1,0);assert(m1une::graph::is_bipartite(directed));autoweak=m1une::graph::connected_components(directed);assert(weak.count==1);m1une::graph::BipartiteMatchingbm(3,2);inte00=bm.add_edge(0,0);inte10=bm.add_edge(1,0);inte11=bm.add_edge(1,1);inte21=bm.add_edge(2,1);assert(bm.left_size()==3);assert(bm.right_size()==2);assert(bm.edge_count()==4);assert(bm.get_edge(e10).left==1);assert(bm.max_matching()==2);assert(bm.matching_size()==2);autopairs=bm.matching();assert(pairs.size()==2);autoleft_match=bm.left_match();autoright_match=bm.right_match();for(constauto&p:pairs){assert(left_match[p.left]==p.right);assert(right_match[p.right]==p.left);}autocover=bm.minimum_vertex_cover();assert(cover.left.empty());assert((cover.right==std::vector<int>{0,1}));assert(cover.size()==2);autoindependent=bm.maximum_independent_set();assert((independent.left==std::vector<int>{0,1,2}));assert(independent.right.empty());autoedge_cover=bm.minimum_edge_cover();assert(edge_cover.has_value());assert(edge_cover->size()==3);std::vector<bool>covered_left(3,false),covered_right(2,false);for(intid:*edge_cover){autoedge=bm.get_edge(id);covered_left[edge.left]=true;covered_right[edge.right]=true;}assert((covered_left==std::vector<bool>{true,true,true}));assert((covered_right==std::vector<bool>{true,true}));bm.erase_edge(e11);bm.erase_edge(e21);assert(!bm.is_edge_alive(e21));assert(bm.edges().size()==2);assert(bm.edges(true).size()==4);assert(bm.max_matching()==1);bm.revive_edge(e21);assert(bm.max_matching()==2);m1une::graph::BipartiteMatchingisolated(1,1);assert(!isolated.minimum_edge_cover().has_value());(void)e00;}voidtest_general_matching(){m1une::graph::GeneralMatchingblossom(6);inte01=blossom.add_edge(0,1);inte12=blossom.add_edge(1,2);inte23=blossom.add_edge(2,3);inte34=blossom.add_edge(3,4);inte40=blossom.add_edge(4,0);inte15=blossom.add_edge(1,5);(void)e12;(void)e23;(void)e34;(void)e40;assert(blossom.size()==6);assert(blossom.edge_count()==6);assert(blossom.get_edge(e01).other(0)==1);assert(blossom.max_matching()==3);assert(blossom.matching_size()==3);automate=blossom.mate();automate_edge=blossom.mate_edge();for(intv=0;v<6;v++){assert(mate[v]!=-1);assert(mate[mate[v]]==v);assert(mate_edge[v]!=-1);}autopairs=blossom.matching();assert(pairs.size()==3);for(constauto&p:pairs){assert(mate[p.from]==p.to);assert(mate[p.to]==p.from);}autoedge_cover=blossom.minimum_edge_cover();assert(edge_cover.has_value());assert(edge_cover->size()==3);std::vector<bool>covered(6,false);for(intid:*edge_cover){autoedge=blossom.get_edge(id);covered[edge.from]=true;covered[edge.to]=true;}assert((covered==std::vector<bool>{true,true,true,true,true,true}));blossom.erase_edge(e15);assert(!blossom.is_edge_alive(e15));assert(blossom.edges().size()==5);assert(blossom.edges(true).size()==6);assert(blossom.max_matching()==2);assert(!blossom.minimum_edge_cover().has_value());blossom.revive_edge(e15);assert(blossom.max_matching()==3);m1une::graph::GeneralMatchingtricky(6);tricky.add_edge(0,1);tricky.add_edge(0,4);tricky.add_edge(1,2);tricky.add_edge(3,4);tricky.add_edge(3,5);tricky.add_edge(4,5);assert(tricky.max_matching()==3);for(constauto&p:tricky.matching()){autoe=tricky.get_edge(p.edge_id);assert((e.from==p.from&&e.to==p.to)||(e.from==p.to&&e.to==p.from));}m1une::graph::GeneralMatchingparallel(4);intp01_removed=parallel.add_edge(0,1);parallel.add_edge(0,1);parallel.add_edge(2,3);parallel.erase_edge(p01_removed);assert(parallel.max_matching()==2);autoparallel_mate_edge=parallel.mate_edge();for(intv=0;v<4;v++)assert(parallel.is_edge_alive(parallel_mate_edge[v]));m1une::graph::GeneralMatchingpath(3);path.add_edge(0,1);path.add_edge(1,2);autopath_cover=path.minimum_edge_cover();assert(path_cover.has_value());assert(path_cover->size()==2);m1une::graph::GeneralMatchingbipartite_general(8);intbg03=bipartite_general.add_edge(0,3);bipartite_general.add_edge(0,7);bipartite_general.add_edge(1,4);bipartite_general.add_edge(2,5);bipartite_general.add_edge(6,3);bipartite_general.add_edge(2,7);bipartite_general.erase_edge(bg03);assert(bipartite_general.max_matching()==4);autobipartite_mate=bipartite_general.mate();for(intv=0;v<8;v++){assert(bipartite_mate[v]!=-1);assert(bipartite_mate[bipartite_mate[v]]==v);}m1une::graph::GeneralMatchingisolated(1);assert(!isolated.minimum_edge_cover().has_value());Graph<int>g(4);intg01=g.add_edge(0,1);intg12=g.add_edge(1,2);intg20=g.add_edge(2,0);intg23=g.add_edge(2,3);(void)g01;(void)g12;(void)g20;autobuilt=m1une::graph::make_general_matching(g);assert(built.matching.max_matching()==2);for(constauto&p:built.matching.matching()){assert(g.is_edge_alive(built.original_edge(p.edge_id)));}assert(g.is_edge_alive(g23));}voidtest_maximum_clique_and_independent_set(){Graph<int>g(7);intremoved_clique_edge=-1;for(inti=0;i<4;i++){for(intj=i+1;j<4;j++){intid=g.add_edge(i,j);if(i==0&&j==2)removed_clique_edge=id;}}g.add_edge(4,0);g.add_edge(4,1);g.add_edge(5,1);g.add_edge(5,2);autoclique=m1une::graph::maximum_clique(g);assert(clique.size()==4);assert((clique.vertices==std::vector<int>{0,1,2,3}));assert(m1une::graph::is_clique(g,clique.vertices));assert(m1une::graph::maximum_clique_size(g)==4);autoindependent=m1une::graph::maximum_independent_set(g);assert(independent.size()==4);assert((independent.vertices==std::vector<int>{3,4,5,6}));assert(m1une::graph::is_independent_set(g,independent.vertices));assert(m1une::graph::maximum_independent_set_size(g)==4);autocover=m1une::graph::minimum_vertex_cover(g);assert(cover.size()==3);assert((cover.vertices==std::vector<int>{0,1,2}));assert(m1une::graph::is_vertex_cover(g,cover.vertices));assert(m1une::graph::minimum_vertex_cover_size(g)==3);assert(!m1une::graph::is_clique(g,std::vector<int>{0,2,4}));assert(!m1une::graph::is_independent_set(g,std::vector<int>{4,0}));assert(!m1une::graph::is_vertex_cover(g,std::vector<int>{0,1}));g.erase_edge(removed_clique_edge);assert(m1une::graph::maximum_clique_size(g)==3);g.revive_edge(removed_clique_edge);assert(m1une::graph::maximum_clique_size(g)==4);Graph<int>directed(3);directed.add_directed_edge(0,1);directed.add_directed_edge(1,2);autodirected_clique=m1une::graph::maximum_clique(directed);autodirected_independent=m1une::graph::maximum_independent_set(directed);autodirected_cover=m1une::graph::minimum_vertex_cover(directed);assert(directed_clique.size()==2);assert(directed_independent.size()==2);assert((directed_independent.vertices==std::vector<int>{0,2}));assert((directed_cover.vertices==std::vector<int>{1}));Graph<int>empty(4);assert(m1une::graph::maximum_clique_size(empty)==1);assert(m1une::graph::maximum_independent_set_size(empty)==4);assert(m1une::graph::minimum_vertex_cover(empty).empty());Graph<int>path(6);for(inti=0;i+1<6;i++)path.add_edge(i,i+1);assert(m1une::graph::maximum_independent_set_size(path)==3);assert(m1une::graph::minimum_vertex_cover_size(path)==3);Graph<int>cycle(5);for(inti=0;i<5;i++)cycle.add_edge(i,(i+1)%5);assert(m1une::graph::maximum_independent_set_size(cycle)==2);assert(m1une::graph::minimum_vertex_cover_size(cycle)==3);Graph<int>none(0);assert(m1une::graph::maximum_clique(none).empty());assert(m1une::graph::maximum_independent_set(none).empty());assert(m1une::graph::minimum_vertex_cover(none).empty());}voidtest_cycle_detection(){Graph<int>dg(3);dg.add_directed_edge(0,1);dg.add_directed_edge(1,2);dg.add_directed_edge(2,0);autodirected=m1une::graph::find_directed_cycle(dg);assert(!directed.empty());assert(directed.vertices.front()==directed.vertices.back());assert(directed.edge_ids.size()+1==directed.vertices.size());Graph<int>ug(4);ug.add_edge(0,1);ug.add_edge(1,2);ug.add_edge(2,0);ug.add_edge(2,3);autoundirected=m1une::graph::find_undirected_cycle(ug);assert(!undirected.empty());assert(undirected.vertices.front()==undirected.vertices.back());}voidtest_kruskal(){Graph<longlong>g(4);g.add_edge(0,1,1);g.add_edge(1,2,2);g.add_edge(2,3,3);g.add_edge(0,3,10);g.add_edge(0,2,4);automst=m1une::graph::kruskal(g);assert(mst.cost==6);assert(mst.edges.size()==3);assert(mst.components==1);assert(mst.is_spanning_tree(g.size()));}voidtest_grid(){m1une::graph::Gridgrid(3,4);assert(grid.height()==3);assert(grid.width()==4);assert(grid.size()==12);assert(grid.inside(2,3));assert(!grid.inside(3,0));assert(grid.id(2,3)==11);assert(grid.pos(6)==std::make_pair(1,2));autoadj4=grid.adj4(0,0);std::vector<std::pair<int,int>>expected_adj4={std::pair<int,int>{0,1},std::pair<int,int>{1,0},};assert(adj4==expected_adj4);autoadj8=grid.adj8(1,1);assert(adj8.size()==8);autoadj4_ids=grid.adj4_ids(grid.id(1,1));std::set<int>expected_ids={grid.id(0,1),grid.id(1,2),grid.id(2,1),grid.id(1,0)};assert(std::set<int>(adj4_ids.begin(),adj4_ids.end())==expected_ids);std::vector<std::string>s={"....",".##.","....",};autopassable=[&](inti,intj){returns[i][j]!='#';};autog4=grid.graph4(passable);assert(g4.size()==grid.size());assert(g4[grid.id(1,1)].empty());autores=m1une::graph::bfs(g4,grid.id(0,0));assert(res.dist[grid.id(2,3)]==5);assert(res.dist[grid.id(1,1)]==-1);autog8=grid.graph8(passable);autores8=m1une::graph::bfs(g8,grid.id(0,0));assert(res8.dist[grid.id(2,3)]==4);autoall4=grid.graph4();assert(all4.edge_count()==17);}intmain(){m1une::utilities::FastInputfast_input;m1une::utilities::FastOutputfast_output;test_graph_container();test_edge_alive();test_bfs();test_dijkstra();test_zero_one_bfs();test_bellman_ford();test_dag_shortest_path();test_warshall_floyd();test_topological_sort();test_scc();test_lowlink();test_bipartite_and_components();test_general_matching();test_maximum_clique_and_independent_set();test_cycle_detection();test_kruskal();test_grid();longlonga,b;fast_input>>a>>b;fast_output<<a+b<<'\n';}