Skip to content

Commit ba061ea

Browse files
chore: update minified library versions
1 parent d408c40 commit ba061ea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+2691
-150
lines changed

cp-algo/min/geometry/closest_pair.hpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,25 @@
44
#include "point.hpp"
55
#include <vector>
66
#include <map>
7-
namespace cp_algo::geometry{template<typename ftype>auto closest_pair(std::vector<point_t<ftype>>const&r){using point=point_t<ftype>;size_t n=size(r);int64_t md=1e18;for(size_t i=0;i<n/100;i++){auto A=random::rng()%n;auto B=random::rng()%n;if(A!=B){md=std::min(md,norm(r[A]-r[B]));if(md==0){return std::pair{A,B};}}}std::map<point,std::vector<size_t>>neigs;md=(int64_t)ceil(sqrt((double)md));for(size_t i=0;i<n;i++){neigs[r[i]/md].push_back(i);}size_t a=0,b=1;md=norm(r[a]-r[b]);for(auto&[p,id]:neigs){for(int dx:{-1,0,1}){for(int dy:{-1,0,1}){auto pp=p+point{dx,dy};if(!neigs.count(pp)){continue;}for(size_t i:neigs[pp]){for(size_t j:id){if(j==i){break;}int64_t cur=norm(r[i]-r[j]);if(cur<md){md=cur;a=i;b=j;}}}}}}return std::pair{a,b};}}
8-
#endif
7+
namespace cp_algo::geometry{template<typename ftype>
8+
auto closest_pair(std::vector<point_t<ftype>>const&r){using point=point_t<ftype>;
9+
size_t n=size(r);
10+
int64_t md=1e18;
11+
for(size_t i=0;i<n/100;i++){auto A=random::rng()%n;
12+
auto B=random::rng()%n;
13+
if(A!=B){md=std::min(md,norm(r[A]-r[B]));
14+
if(md==0){return std::pair{A,B};}}}
15+
std::map<point,std::vector<size_t>>neigs;
16+
md=(int64_t)ceil(sqrt((double)md));
17+
for(size_t i=0;i<n;i++){neigs[r[i]/md].push_back(i);}
18+
size_t a=0,b=1;
19+
md=norm(r[a]-r[b]);
20+
for(auto&[p,id]:neigs){for(int dx:{-1,0,1}){for(int dy:{-1,0,1}){auto pp=p+point{dx,dy};
21+
if(!neigs.count(pp)){continue;}
22+
for(size_t i:neigs[pp]){for(size_t j:id){if(j==i){break;}
23+
int64_t cur=norm(r[i]-r[j]);
24+
if(cur<md){md=cur;
25+
a=i;
26+
b=j;}}}}}}
27+
return std::pair{a,b};}}
28+
#endif

cp-algo/min/geometry/convex_hull.hpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,17 @@
55
#include <utility>
66
#include <vector>
77
#include <ranges>
8-
namespace cp_algo::geometry{template<typename ftype>std::vector<point_t<ftype>>convex_hull(std::vector<point_t<ftype>>r){using point=point_t<ftype>;std::ranges::sort(r);if(size(r)<=1||r[0]==r.back()){return empty(r)?r:std::vector{r[0]};}std::vector<point>hull={r[0]};for(int half:{0,1}){size_t base=size(hull);for(auto it:std::views::drop(r,1)){while(size(hull)>=base+1){point a=hull.back();if(point::ccw(it-a,end(hull)[-2]-a)){break;}else{hull.pop_back();}}hull.push_back(it);}std::ranges::reverse(r);std::ignore=half;}hull.pop_back();return hull;}}
9-
#endif
8+
namespace cp_algo::geometry{template<typename ftype>
9+
std::vector<point_t<ftype>>convex_hull(std::vector<point_t<ftype>>r){using point=point_t<ftype>;
10+
std::ranges::sort(r);
11+
if(size(r)<=1||r[0]==r.back()){return empty(r)?r:std::vector{r[0]};}
12+
std::vector<point>hull={r[0]};
13+
for(int half:{0,1}){size_t base=size(hull);
14+
for(auto it:std::views::drop(r,1)){while(size(hull)>=base+1){point a=hull.back();
15+
if(point::ccw(it-a,end(hull)[-2]-a)){break;}else{hull.pop_back();}}
16+
hull.push_back(it);}
17+
std::ranges::reverse(r);
18+
std::ignore=half;}
19+
hull.pop_back();
20+
return hull;}}
21+
#endif

cp-algo/min/geometry/point.hpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,23 @@
22
#define CP_ALGO_GEOMETRY_POINT_HPP
33
#include "../util/complex.hpp"
44
#include <iostream>
5-
namespace cp_algo::geometry{template<typename ftype>struct point_t:complex<ftype>{using Base=complex<ftype>;using Base::Base;point_t(Base const&t):Base(t){}auto operator<=>(point_t const&t)const{return std::pair{y(),-x()}<=>std::pair{t.y(),-t.x()};}ftype x()const{return Base::real();}ftype y()const{return Base::imag();}point_t cmul(point_t const&t)const{return conj(*this)*t;}ftype dot(point_t const&t)const{return cmul(t).x();}ftype cross(point_t const&t)const{return cmul(t).y();}static constexpr point_t O={0,0};int half()const{return*this<O?-1:*this==O?0:1;}static bool ccw(point_t const&a,point_t const&b){return a.cross(b)>0;}static bool ccw_abs(point_t const&a,point_t const&b){return std::tuple{a.half(),(ftype)0,norm(a)}<std::tuple{b.half(),a.cross(b),norm(b)};}void read(){ftype _x,_y;std::cin>>_x>>_y;*this={_x,_y};}void print()const{std::cout<<x()<<' '<<y()<<"\n";}};}
6-
#endif
5+
namespace cp_algo::geometry{template<typename ftype>
6+
struct point_t:complex<ftype>{using Base=complex<ftype>;
7+
using Base::Base;
8+
point_t(Base const&t):Base(t){}
9+
auto operator<=>(point_t const&t)const{return std::pair{y(),-x()}<=>std::pair{t.y(),-t.x()};}
10+
ftype x()const{return Base::real();}
11+
ftype y()const{return Base::imag();}
12+
point_t cmul(point_t const&t)const{return conj(*this)*t;}
13+
ftype dot(point_t const&t)const{return cmul(t).x();}
14+
ftype cross(point_t const&t)const{return cmul(t).y();}
15+
static constexpr point_t O={0,0};
16+
int half()const{return*this<O?-1:*this==O?0:1;}
17+
static bool ccw(point_t const&a,point_t const&b){return a.cross(b)>0;}
18+
static bool ccw_abs(point_t const&a,point_t const&b){return std::tuple{a.half(),(ftype)0,norm(a)}<
19+
std::tuple{b.half(),a.cross(b),norm(b)};}
20+
void read(){ftype _x,_y;
21+
std::cin>>_x>>_y;
22+
*this={_x,_y};}
23+
void print()const{std::cout<<x()<<' '<<y()<<"\n";}};}
24+
#endif

cp-algo/min/graph/base.hpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,40 @@
44
#include "concepts.hpp"
55
#include "../structures/stack_union.hpp"
66
#include <ranges>
7-
namespace cp_algo::graph{using edge_index=int;template<edge_type _edge_t=edge_base,graph_mode _mode=undirected>struct graph{using edge_t=_edge_t;static constexpr auto mode=_mode;using incidence_list=structures::stack_union<edge_index>;graph(int n,int v0=0):v0(v0),adj(n){}graph transpose()const{static_assert(mode==directed,"transpose is only defined for directed graphs");graph<edge_t,mode>gt(n(),v0);for(auto v:nodes()){for(auto e:outgoing(v)){gt.add_edge(edge(e).traverse(v),edge(e));}}return gt;}edge_index add_edge(node_index u,edge_t e){edge_index idx=(edge_index)size(E);E.push_back(e);adj.push(u,idx);if constexpr(mode==undirected){adj.push(e.traverse(u),idx);}return idx;}edge_index add_edge(node_index u,auto... Args){return add_edge(u,edge_t(u,Args...));}void read_edges(node_index m){adj.reserve(mode==undirected?2*m:m);for(edge_index i=0;i<m;i++){auto[u,e]=edge_t::read(v0);add_edge(u,e);}}auto outgoing(node_index v)const{return adj[v];}auto edges()const{return E|std::views::all;}auto nodes()const{return std::views::iota(node_index(0),n());}auto edge_indices()const{return std::views::iota(edge_index(0),m());}auto&&incidence_lists(this auto&&self){return self.adj;}auto&&edge(this auto&&self,edge_index e){return self.E[e];}node_index n()const{return(node_index)incidence_lists().size();}edge_index m()const{return(edge_index)edges().size();}private:node_index v0;big_vector<edge_t>E;incidence_list adj;};template<edge_type edge_t=edge_base>using digraph=graph<edge_t,directed>;template<weighted_edge_type edge_t=weighted_edge,graph_mode mode=undirected>using weighted_graph=graph<edge_t,mode>;template<weighted_edge_type edge_t=weighted_edge>using weighted_digraph=digraph<edge_t>;}
8-
#endif
7+
namespace cp_algo::graph{using edge_index=int;
8+
template<edge_type _edge_t=edge_base,graph_mode _mode=undirected>
9+
struct graph{using edge_t=_edge_t;
10+
static constexpr auto mode=_mode;
11+
using incidence_list=structures::stack_union<edge_index>;
12+
graph(int n,int v0=0):v0(v0),adj(n){}
13+
graph transpose()const{static_assert(mode==directed,"transpose is only defined for directed graphs");
14+
graph<edge_t,mode>gt(n(),v0);
15+
for(auto v:nodes()){for(auto e:outgoing(v)){gt.add_edge(edge(e).traverse(v),edge(e));}}
16+
return gt;}
17+
edge_index add_edge(node_index u,edge_t e){edge_index idx=(edge_index)size(E);
18+
E.push_back(e);
19+
adj.push(u,idx);
20+
if constexpr(mode==undirected){adj.push(e.traverse(u),idx);}
21+
return idx;}
22+
edge_index add_edge(node_index u,auto... Args){return add_edge(u,edge_t(u,Args...));}
23+
void read_edges(node_index m){adj.reserve(mode==undirected?2*m:m);
24+
for(edge_index i=0;i<m;i++){auto[u,e]=edge_t::read(v0);
25+
add_edge(u,e);}}
26+
auto outgoing(node_index v)const{return adj[v];}
27+
auto edges()const{return E|std::views::all;}
28+
auto nodes()const{return std::views::iota(node_index(0),n());}
29+
auto edge_indices()const{return std::views::iota(edge_index(0),m());}
30+
auto&&incidence_lists(this auto&&self){return self.adj;}
31+
auto&&edge(this auto&&self,edge_index e){return self.E[e];}
32+
node_index n()const{return(node_index)incidence_lists().size();}
33+
edge_index m()const{return(edge_index)edges().size();}
34+
private:node_index v0;
35+
big_vector<edge_t>E;
36+
incidence_list adj;};
37+
template<edge_type edge_t=edge_base>
38+
using digraph=graph<edge_t,directed>;
39+
template<weighted_edge_type edge_t=weighted_edge,graph_mode mode=undirected>
40+
using weighted_graph=graph<edge_t,mode>;
41+
template<weighted_edge_type edge_t=weighted_edge>
42+
using weighted_digraph=digraph<edge_t>;}
43+
#endif

cp-algo/min/graph/concepts.hpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,25 @@
22
#define CP_ALGO_GRAPH_CONCEPTS_HPP
33
#include "edge_types.hpp"
44
#include <type_traits>
5-
namespace cp_algo::graph{enum graph_mode{directed,undirected};template<typename T,typename=void>struct graph_traits:std::false_type{};template<typename T>struct graph_traits<T,std::void_t<typename T::edge_t,decltype(T::mode)>>:std::true_type{using edge_t=typename T::edge_t;static constexpr auto mode=T::mode;static constexpr bool is_directed=mode==directed;static constexpr bool is_undirected=mode==undirected;static constexpr bool is_weighted=weighted_edge_type<edge_t>;};template<typename G>concept graph_type=graph_traits<G>::value;template<typename G>concept digraph_type=graph_type<G>&&graph_traits<G>::is_directed;template<typename G>concept undirected_graph_type=graph_type<G>&&graph_traits<G>::is_undirected;template<typename G>concept weighted_graph_type=graph_type<G>&&graph_traits<G>::is_weighted;template<typename G>concept weighted_digraph_type=digraph_type<G>&&graph_traits<G>::is_weighted;template<typename G>concept weighted_undirected_graph_type=undirected_graph_type<G>&&graph_traits<G>::is_weighted;}
6-
#endif
5+
namespace cp_algo::graph{enum graph_mode{directed,undirected};
6+
template<typename T,typename=void>
7+
struct graph_traits:std::false_type{};
8+
template<typename T>
9+
struct graph_traits<T,std::void_t<typename T::edge_t,decltype(T::mode)>>:std::true_type{using edge_t=typename T::edge_t;
10+
static constexpr auto mode=T::mode;
11+
static constexpr bool is_directed=mode==directed;
12+
static constexpr bool is_undirected=mode==undirected;
13+
static constexpr bool is_weighted=weighted_edge_type<edge_t>;};
14+
template<typename G>
15+
concept graph_type=graph_traits<G>::value;
16+
template<typename G>
17+
concept digraph_type=graph_type<G>&&graph_traits<G>::is_directed;
18+
template<typename G>
19+
concept undirected_graph_type=graph_type<G>&&graph_traits<G>::is_undirected;
20+
template<typename G>
21+
concept weighted_graph_type=graph_type<G>&&graph_traits<G>::is_weighted;
22+
template<typename G>
23+
concept weighted_digraph_type=digraph_type<G>&&graph_traits<G>::is_weighted;
24+
template<typename G>
25+
concept weighted_undirected_graph_type=undirected_graph_type<G>&&graph_traits<G>::is_weighted;}
26+
#endif

cp-algo/min/graph/cycle.hpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,19 @@
33
#include "dfs.hpp"
44
#include "base.hpp"
55
#include <deque>
6-
namespace cp_algo::graph{template<graph_type graph>struct cycle_context:dfs_context<graph>{using base=dfs_context<graph>;using base::base;std::deque<edge_index>cycle;bool closed=false;int v0;void on_return_from_child(node_index v,edge_index e){if(!empty(cycle)&&!closed){cycle.push_front(e);closed|=v==v0;}}void on_back_edge(node_index v,edge_index e){if(empty(cycle)){v0=base::g->edge(e).traverse(v);base::done=true;closed=v==v0;cycle.push_front(e);}}};template<graph_type graph>std::pair<node_index,std::deque<edge_index>>find_cycle(graph const&g){auto context=dfs<cycle_context>(g);return{context.v0,context.cycle};}}
7-
#endif
6+
namespace cp_algo::graph{template<graph_type graph>
7+
struct cycle_context:dfs_context<graph>{using base=dfs_context<graph>;
8+
using base::base;
9+
std::deque<edge_index>cycle;
10+
bool closed=false;
11+
int v0;
12+
void on_return_from_child(node_index v,edge_index e){if(!empty(cycle)&&!closed){cycle.push_front(e);
13+
closed|=v==v0;}}
14+
void on_back_edge(node_index v,edge_index e){if(empty(cycle)){v0=base::g->edge(e).traverse(v);
15+
base::done=true;
16+
closed=v==v0;
17+
cycle.push_front(e);}}};
18+
template<graph_type graph>
19+
std::pair<node_index,std::deque<edge_index>>find_cycle(graph const&g){auto context=dfs<cycle_context>(g);
20+
return{context.v0,context.cycle};}}
21+
#endif

cp-algo/min/graph/dfs.hpp

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,56 @@
33
#include "base.hpp"
44
#include <variant>
55
#include <stack>
6-
namespace cp_algo::graph{enum node_state{unvisited,visiting,visited,blocked};template<graph_type graph>struct dfs_context{big_vector<node_state>state;graph const*g;bool done=false;dfs_context(graph const&g):state(g.n()),g(&g){}void on_enter(node_index){}void on_tree_edge(node_index,edge_index){}void on_return_from_child(node_index,edge_index){}void on_back_edge(node_index,edge_index){}void on_forward_cross_edge(node_index,edge_index){}void on_exit(node_index){}};template<template<typename>class Context,graph_type graph>Context<graph>dfs(graph const&g){Context<graph>context(g);auto const&adj=g.incidence_lists();struct frame{node_index v;[[no_unique_address]]std::conditional_t<undirected_graph_type<graph>,edge_index,std::monostate>ep;int sv;enum{INIT,PROCESS_EDGES,HANDLE_CHILD}state;};std::stack<frame>dfs_stack;for(auto root:g.nodes()){if(context.done)break;if(context.state[root]!=unvisited)continue;if constexpr(undirected_graph_type<graph>){dfs_stack.push({root,-1,0,frame::INIT});}else{dfs_stack.push({root,{},0,frame::INIT});}while(!empty(dfs_stack)){auto&f=dfs_stack.top();if(f.state==frame::INIT){context.state[f.v]=visiting;context.on_enter(f.v);f.sv=adj.head[f.v];f.state=frame::PROCESS_EDGES;continue;}if(f.state==frame::HANDLE_CHILD){auto e=adj.data[f.sv];f.sv=adj.next[f.sv];context.on_return_from_child(f.v,e);f.state=frame::PROCESS_EDGES;continue;}bool found_child=false;while(f.sv!=0&&!context.done){auto e=adj.data[f.sv];if constexpr(undirected_graph_type<graph>){if(f.ep==e){f.sv=adj.next[f.sv];continue;}}node_index u=g.edge(e).traverse(f.v);if(context.state[u]==unvisited){context.on_tree_edge(f.v,e);f.state=frame::HANDLE_CHILD;if constexpr(undirected_graph_type<graph>){dfs_stack.push({u,e,0,frame::INIT});}else{dfs_stack.push({u,{},0,frame::INIT});}found_child=true;break;}else if(context.state[u]==visiting){context.on_back_edge(f.v,e);}else if(context.state[u]==visited){context.on_forward_cross_edge(f.v,e);}f.sv=adj.next[f.sv];}if(found_child)continue;context.state[f.v]=visited;context.on_exit(f.v);dfs_stack.pop();}}return context;}}
7-
#endif
6+
namespace cp_algo::graph{enum node_state{unvisited,visiting,visited,blocked};
7+
template<graph_type graph>
8+
struct dfs_context{big_vector<node_state>state;
9+
graph const*g;
10+
bool done=false;
11+
dfs_context(graph const&g):state(g.n()),g(&g){}
12+
void on_enter(node_index){}
13+
void on_tree_edge(node_index,edge_index){}
14+
void on_return_from_child(node_index,edge_index){}
15+
void on_back_edge(node_index,edge_index){}
16+
void on_forward_cross_edge(node_index,edge_index){}
17+
void on_exit(node_index){}};
18+
template<template<typename>class Context,graph_type graph>
19+
Context<graph>dfs(graph const&g){Context<graph>context(g);
20+
auto const&adj=g.incidence_lists();
21+
struct frame{node_index v;
22+
[[no_unique_address]]std::conditional_t<
23+
undirected_graph_type<graph>,
24+
edge_index,std::monostate>ep;
25+
int sv;
26+
enum{INIT,PROCESS_EDGES,HANDLE_CHILD}state;};
27+
std::stack<frame>dfs_stack;
28+
for(auto root:g.nodes()){if(context.done)break;
29+
if(context.state[root]!=unvisited)continue;
30+
if constexpr(undirected_graph_type<graph>){dfs_stack.push({root,-1,0,frame::INIT});}else{dfs_stack.push({root,{},0,frame::INIT});}
31+
while(!empty(dfs_stack)){auto&f=dfs_stack.top();
32+
if(f.state==frame::INIT){context.state[f.v]=visiting;
33+
context.on_enter(f.v);
34+
f.sv=adj.head[f.v];
35+
f.state=frame::PROCESS_EDGES;
36+
continue;}
37+
if(f.state==frame::HANDLE_CHILD){auto e=adj.data[f.sv];
38+
f.sv=adj.next[f.sv];
39+
context.on_return_from_child(f.v,e);
40+
f.state=frame::PROCESS_EDGES;
41+
continue;}
42+
bool found_child=false;
43+
while(f.sv!=0&&!context.done){auto e=adj.data[f.sv];
44+
if constexpr(undirected_graph_type<graph>){if(f.ep==e){f.sv=adj.next[f.sv];
45+
continue;}}
46+
node_index u=g.edge(e).traverse(f.v);
47+
if(context.state[u]==unvisited){context.on_tree_edge(f.v,e);
48+
f.state=frame::HANDLE_CHILD;
49+
if constexpr(undirected_graph_type<graph>){dfs_stack.push({u,e,0,frame::INIT});}else{dfs_stack.push({u,{},0,frame::INIT});}
50+
found_child=true;
51+
break;}else if(context.state[u]==visiting){context.on_back_edge(f.v,e);}else if(context.state[u]==visited){context.on_forward_cross_edge(f.v,e);}
52+
f.sv=adj.next[f.sv];}
53+
if(found_child)continue;
54+
context.state[f.v]=visited;
55+
context.on_exit(f.v);
56+
dfs_stack.pop();}}
57+
return context;}}
58+
#endif

cp-algo/min/graph/dfs_time.hpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,27 @@
22
#define CP_ALGO_GRAPH_DFS_TIME_HPP
33
#include "dfs.hpp"
44
#include "base.hpp"
5-
namespace cp_algo::graph{template<graph_type graph>struct dfs_time_context:dfs_context<graph>{using base=dfs_context<graph>;big_vector<int>tin;int timer;dfs_time_context(graph const&g):base(g),tin(g.n()),timer(0){}void on_enter(node_index v){tin[v]=timer++;}};template<graph_type graph>struct dfs_time_range_context:dfs_time_context<graph>{using base=dfs_time_context<graph>;big_vector<int>tout;dfs_time_range_context(graph const&g):base(g),tout(g.n()){}void on_exit(node_index v){tout[v]=base::timer;}};template<graph_type graph>struct dfs_low_context:dfs_time_context<graph>{using base=dfs_time_context<graph>;big_vector<int>low;dfs_low_context(graph const&g):base(g),low(g.n()){}void on_enter(node_index v){base::on_enter(v);low[v]=base::tin[v];}void on_return_from_child(node_index v,edge_index e){node_index u=base::g->edge(e).traverse(v);low[v]=std::min(low[v],low[u]);}void on_back_edge(node_index v,edge_index e){node_index u=base::g->edge(e).traverse(v);low[v]=std::min(low[v],base::tin[u]);}void on_forward_cross_edge(node_index v,edge_index e){node_index u=base::g->edge(e).traverse(v);low[v]=std::min(low[v],base::tin[u]);}};}
6-
#endif
5+
namespace cp_algo::graph{template<graph_type graph>
6+
struct dfs_time_context:dfs_context<graph>{using base=dfs_context<graph>;
7+
big_vector<int>tin;
8+
int timer;
9+
dfs_time_context(graph const&g):base(g),tin(g.n()),timer(0){}
10+
void on_enter(node_index v){tin[v]=timer++;}};
11+
template<graph_type graph>
12+
struct dfs_time_range_context:dfs_time_context<graph>{using base=dfs_time_context<graph>;
13+
big_vector<int>tout;
14+
dfs_time_range_context(graph const&g):base(g),tout(g.n()){}
15+
void on_exit(node_index v){tout[v]=base::timer;}};
16+
template<graph_type graph>
17+
struct dfs_low_context:dfs_time_context<graph>{using base=dfs_time_context<graph>;
18+
big_vector<int>low;
19+
dfs_low_context(graph const&g):base(g),low(g.n()){}
20+
void on_enter(node_index v){base::on_enter(v);
21+
low[v]=base::tin[v];}
22+
void on_return_from_child(node_index v,edge_index e){node_index u=base::g->edge(e).traverse(v);
23+
low[v]=std::min(low[v],low[u]);}
24+
void on_back_edge(node_index v,edge_index e){node_index u=base::g->edge(e).traverse(v);
25+
low[v]=std::min(low[v],base::tin[u]);}
26+
void on_forward_cross_edge(node_index v,edge_index e){node_index u=base::g->edge(e).traverse(v);
27+
low[v]=std::min(low[v],base::tin[u]);}};}
28+
#endif

0 commit comments

Comments
 (0)