Skip to content

Commit f199ef5

Browse files
chore: update minified library versions
1 parent 18ed58e commit f199ef5

File tree

6 files changed

+8
-6
lines changed

6 files changed

+8
-6
lines changed

cp-algo/min/graph/dfs.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
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;}}
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;};big_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;}}
77
#endif

cp-algo/min/graph/euler.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
#include <utility>
99
#include <vector>
1010
#include <stack>
11-
namespace cp_algo::graph{template<graph_type graph>std::optional<node_index>euler_start(graph const&g){big_vector<int>deg(g.n());std::optional<node_index>default_start=0;for(auto v:g.nodes()){for(auto e:g.outgoing(v)){deg[v]++;default_start=v;if constexpr(digraph_type<graph>){deg[g.edge(e).traverse(v)]--;}}}if constexpr(undirected_graph_type<graph>){for(auto&it:deg){it%=2;}}auto is_start=[&](int v){return deg[v]>0;};auto starts=std::ranges::count_if(g.nodes(),is_start);auto need_starts=undirected_graph_type<graph>?2:1;if(starts>need_starts){return std::nullopt;}else if(starts==need_starts){auto start=*std::ranges::find_if(g.nodes(),is_start);if(deg[start]==1){return start;}else{return std::nullopt;}}return default_start;}template<graph_type graph>big_deque<edge_index>try_euler_trail(graph const&g,node_index v0){big_deque<edge_index>trail;enum state{unvisited,visited};big_vector<state>state(g.m());auto const&adj=g.incidence_lists();auto head=adj.head;struct stack_frame{edge_index ep;node_index v;};std::stack<stack_frame>stack;stack.push({-1,v0});while(!empty(stack)){auto[ep,v]=stack.top();bool found_edge=false;while(head[v]!=0){auto e=adj.data[std::exchange(head[v],adj.next[head[v]])];if(state[e]==unvisited){state[e]=visited;stack.push({e,g.edge(e).traverse(v)});found_edge=true;break;}}if(!found_edge){stack.pop();if(~ep){trail.push_front(ep);}}}return trail;}template<graph_type graph>std::optional<std::pair<node_index,big_deque<edge_index>>>euler_trail(graph const&g){auto v0=euler_start(g);if(!v0){return std::nullopt;}auto result=try_euler_trail(g,*v0);if((edge_index)result.size()!=g.m()){return std::nullopt;}return{{*v0,std::move(result)}};}}
11+
namespace cp_algo::graph{template<graph_type graph>std::optional<node_index>euler_start(graph const&g){big_vector<int>deg(g.n());std::optional<node_index>default_start=0;for(auto v:g.nodes()){for(auto e:g.outgoing(v)){deg[v]++;default_start=v;if constexpr(digraph_type<graph>){deg[g.edge(e).traverse(v)]--;}}}if constexpr(undirected_graph_type<graph>){for(auto&it:deg){it%=2;}}auto is_start=[&](int v){return deg[v]>0;};auto starts=std::ranges::count_if(g.nodes(),is_start);auto need_starts=undirected_graph_type<graph>?2:1;if(starts>need_starts){return std::nullopt;}else if(starts==need_starts){auto start=*std::ranges::find_if(g.nodes(),is_start);if(deg[start]==1){return start;}else{return std::nullopt;}}return default_start;}template<graph_type graph>big_deque<edge_index>try_euler_trail(graph const&g,node_index v0){big_deque<edge_index>trail;enum state{unvisited,visited};big_vector<state>state(g.m());auto const&adj=g.incidence_lists();auto head=adj.head;struct stack_frame{edge_index ep;node_index v;};big_stack<stack_frame>stack;stack.push({-1,v0});while(!empty(stack)){auto[ep,v]=stack.top();bool found_edge=false;while(head[v]!=0){auto e=adj.data[std::exchange(head[v],adj.next[head[v]])];if(state[e]==unvisited){state[e]=visited;stack.push({e,g.edge(e).traverse(v)});found_edge=true;break;}}if(!found_edge){stack.pop();if(~ep){trail.push_front(ep);}}}return trail;}template<graph_type graph>std::optional<std::pair<node_index,big_deque<edge_index>>>euler_trail(graph const&g){auto v0=euler_start(g);if(!v0){return std::nullopt;}auto result=try_euler_trail(g,*v0);if((edge_index)result.size()!=g.m()){return std::nullopt;}return{{*v0,std::move(result)}};}}
1212
#endif

cp-algo/min/graph/shortest_path.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
#include "base.hpp"
44
#include <algorithm>
55
#include <queue>
6-
namespace cp_algo::graph{struct shortest_path_context{big_vector<int64_t>dist;big_vector<edge_index>pre;static constexpr int64_t inf=1e18;shortest_path_context(int n):dist(n,inf),pre(n){}};struct dijkstra_context:shortest_path_context{struct que_t{int64_t dist;node_index v;bool operator<(que_t const&other)const{return dist>other.dist;}};std::priority_queue<que_t>pq;dijkstra_context(int n):shortest_path_context(n){}void push(node_index,edge_index,node_index v){pq.push({dist[v],v});}std::optional<node_index>next_node(){while(!empty(pq)){auto[dv,v]=pq.top();pq.pop();if(dv==dist[v]){return v;}}return std::nullopt;}};struct spfa_context:shortest_path_context{std::queue<node_index>que;big_vector<char>flags;static constexpr char in_queue=1;static constexpr char invalidated=2;spfa_context(int n):shortest_path_context(n),flags(n){}void push(node_index,edge_index,node_index v){if(!(flags[v]&in_queue)){que.push(v);flags[v]|=in_queue;}}std::optional<node_index>next_node(){while(!que.empty()){node_index v=que.front();que.pop();flags[v]&=~in_queue;if(!(flags[v]&invalidated)){return v;}}return std::nullopt;}};struct deep_spfa_context:spfa_context{struct traverse_edge{edge_index e;node_index v;};big_vector<std::basic_string<traverse_edge>>dependents;deep_spfa_context(int n):spfa_context(n),dependents(n){}void push(node_index u,edge_index e,node_index v){invalidate_subtree(v);dependents[u].push_back({e,v});flags[v]&=~invalidated;spfa_context::push(u,e,v);}void invalidate_subtree(node_index v){big_vector<node_index>to_invalidate={v};while(!empty(to_invalidate)){node_index u=to_invalidate.back();to_invalidate.pop_back();flags[u]|=invalidated;flags[u]&=~in_queue;for(auto[e,v]:dependents[u]){if(pre[v]==e){to_invalidate.push_back(v);}}dependents[u].clear();}}};template<typename Context,weighted_graph_type graph>Context sssp_impl(graph const&g,node_index s){Context context(g.n());context.dist[s]=0;context.pre[s]=-1;context.push(s,-1,s);while(auto ov=context.next_node()){node_index v=*ov;for(auto e:g.outgoing(v)){node_index u=g.edge(e).traverse(v);auto w=g.edge(e).w;if(context.dist[v]+w<context.dist[u]){context.dist[u]=context.dist[v]+w;context.pre[u]=e;context.push(v,e,u);}}}return context;}template<weighted_graph_type graph>shortest_path_context dijkstra(graph const&g,node_index s){return sssp_impl<dijkstra_context>(g,s);}template<weighted_graph_type graph>shortest_path_context spfa(graph const&g,node_index s){return sssp_impl<spfa_context>(g,s);}template<weighted_graph_type graph>shortest_path_context deep_spfa(graph const&g,node_index s){return sssp_impl<deep_spfa_context>(g,s);}template<weighted_graph_type graph>shortest_path_context single_source_shortest_path(graph const&g,node_index s){bool negative_edges=false;for(auto e:g.edges()){negative_edges|=e.w<0;}return negative_edges?deep_spfa(g,s):dijkstra(g,s);}big_vector<edge_index>recover_path(auto const&g,auto const&pre,node_index s,node_index t){big_vector<edge_index>path;node_index v=t;while(v!=s){path.push_back(pre[v]);v=g.edge(pre[v]).traverse(v);}std::ranges::reverse(path);return path;}template<weighted_graph_type graph>std::optional<std::pair<int64_t,big_vector<edge_index>>>shortest_path(graph const&g,node_index s,node_index t){auto[dist,pre]=single_source_shortest_path(g,s);if(dist[t]==shortest_path_context::inf){return std::nullopt;}return{{dist[t],recover_path(g,pre,s,t)}};}}
6+
namespace cp_algo::graph{struct shortest_path_context{big_vector<int64_t>dist;big_vector<edge_index>pre;static constexpr int64_t inf=1e18;shortest_path_context(int n):dist(n,inf),pre(n){}};struct dijkstra_context:shortest_path_context{struct que_t{int64_t dist;node_index v;bool operator<(que_t const&other)const{return dist>other.dist;}};std::priority_queue<que_t>pq;dijkstra_context(int n):shortest_path_context(n){}void push(node_index,edge_index,node_index v){pq.push({dist[v],v});}std::optional<node_index>next_node(){while(!empty(pq)){auto[dv,v]=pq.top();pq.pop();if(dv==dist[v]){return v;}}return std::nullopt;}};struct spfa_context:shortest_path_context{big_queue<node_index>que;big_vector<char>flags;static constexpr char in_queue=1;static constexpr char invalidated=2;spfa_context(int n):shortest_path_context(n),flags(n){}void push(node_index,edge_index,node_index v){if(!(flags[v]&in_queue)){que.push(v);flags[v]|=in_queue;}}std::optional<node_index>next_node(){while(!que.empty()){node_index v=que.front();que.pop();flags[v]&=~in_queue;if(!(flags[v]&invalidated)){return v;}}return std::nullopt;}};struct deep_spfa_context:spfa_context{struct traverse_edge{edge_index e;node_index v;};big_vector<std::basic_string<traverse_edge>>dependents;deep_spfa_context(int n):spfa_context(n),dependents(n){}void push(node_index u,edge_index e,node_index v){invalidate_subtree(v);dependents[u].push_back({e,v});flags[v]&=~invalidated;spfa_context::push(u,e,v);}void invalidate_subtree(node_index v){big_vector<node_index>to_invalidate={v};while(!empty(to_invalidate)){node_index u=to_invalidate.back();to_invalidate.pop_back();flags[u]|=invalidated;flags[u]&=~in_queue;for(auto[e,v]:dependents[u]){if(pre[v]==e){to_invalidate.push_back(v);}}dependents[u].clear();}}};template<typename Context,weighted_graph_type graph>Context sssp_impl(graph const&g,node_index s){Context context(g.n());context.dist[s]=0;context.pre[s]=-1;context.push(s,-1,s);while(auto ov=context.next_node()){node_index v=*ov;for(auto e:g.outgoing(v)){node_index u=g.edge(e).traverse(v);auto w=g.edge(e).w;if(context.dist[v]+w<context.dist[u]){context.dist[u]=context.dist[v]+w;context.pre[u]=e;context.push(v,e,u);}}}return context;}template<weighted_graph_type graph>shortest_path_context dijkstra(graph const&g,node_index s){return sssp_impl<dijkstra_context>(g,s);}template<weighted_graph_type graph>shortest_path_context spfa(graph const&g,node_index s){return sssp_impl<spfa_context>(g,s);}template<weighted_graph_type graph>shortest_path_context deep_spfa(graph const&g,node_index s){return sssp_impl<deep_spfa_context>(g,s);}template<weighted_graph_type graph>shortest_path_context single_source_shortest_path(graph const&g,node_index s){bool negative_edges=false;for(auto e:g.edges()){negative_edges|=e.w<0;}return negative_edges?deep_spfa(g,s):dijkstra(g,s);}big_vector<edge_index>recover_path(auto const&g,auto const&pre,node_index s,node_index t){big_vector<edge_index>path;node_index v=t;while(v!=s){path.push_back(pre[v]);v=g.edge(pre[v]).traverse(v);}std::ranges::reverse(path);return path;}template<weighted_graph_type graph>std::optional<std::pair<int64_t,big_vector<edge_index>>>shortest_path(graph const&g,node_index s,node_index t){auto[dist,pre]=single_source_shortest_path(g,s);if(dist[t]==shortest_path_context::inf){return std::nullopt;}return{{dist[t],recover_path(g,pre,s,t)}};}}
77
#endif

cp-algo/min/graph/tarjan.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66
#include <algorithm>
77
#include <cassert>
88
#include <stack>
9-
namespace cp_algo::graph{template<graph_type graph>struct tarjan_context:dfs_low_context<graph>{using base=dfs_low_context<graph>;std::stack<int>stack;structures::csr<node_index>components;tarjan_context(graph const&g):base(g){components.reserve_data(g.n());}void on_enter(node_index v){base::on_enter(v);stack.push(v);}void collect(node_index v){components.new_row();node_index u;do{u=stack.top();stack.pop();base::state[u]=blocked;components.push(u);}while(u!=v);}};template<graph_type graph>struct exit_context:tarjan_context<graph>{using tarjan_context<graph>::tarjan_context;void on_exit(node_index v){if(this->low[v]==this->tin[v]){this->collect(v);}}};template<digraph_type graph>auto strongly_connected_components(graph const&g){return dfs<exit_context>(g).components;}template<undirected_graph_type graph>auto two_edge_connected_components(graph const&g){return dfs<exit_context>(g).components;}template<undirected_graph_type graph>struct bcc_context:tarjan_context<graph>{using base=tarjan_context<graph>;using base::base;void on_return_from_child(node_index v,edge_index e){base::on_return_from_child(v,e);node_index u=base::g->edge(e).traverse(v);if(base::low[u]>=base::tin[v]){base::collect(u);base::components.push(v);}}void on_exit(node_index v){if(std::empty(base::g->outgoing(v))){base::collect(v);}}};template<undirected_graph_type graph>auto biconnected_components(graph const&g){return dfs<bcc_context>(g).components;}}
9+
namespace cp_algo::graph{template<graph_type graph>struct tarjan_context:dfs_low_context<graph>{using base=dfs_low_context<graph>;big_stack<int>stack;structures::csr<node_index>components;tarjan_context(graph const&g):base(g){components.reserve_data(g.n());}void on_enter(node_index v){base::on_enter(v);stack.push(v);}void collect(node_index v){components.new_row();node_index u;do{u=stack.top();stack.pop();base::state[u]=blocked;components.push(u);}while(u!=v);}};template<graph_type graph>struct exit_context:tarjan_context<graph>{using tarjan_context<graph>::tarjan_context;void on_exit(node_index v){if(this->low[v]==this->tin[v]){this->collect(v);}}};template<digraph_type graph>auto strongly_connected_components(graph const&g){return dfs<exit_context>(g).components;}template<undirected_graph_type graph>auto two_edge_connected_components(graph const&g){return dfs<exit_context>(g).components;}template<undirected_graph_type graph>struct bcc_context:tarjan_context<graph>{using base=tarjan_context<graph>;using base::base;void on_return_from_child(node_index v,edge_index e){base::on_return_from_child(v,e);node_index u=base::g->edge(e).traverse(v);if(base::low[u]>=base::tin[v]){base::collect(u);base::components.push(v);}}void on_exit(node_index v){if(std::empty(base::g->outgoing(v))){base::collect(v);}}};template<undirected_graph_type graph>auto biconnected_components(graph const&g){return dfs<bcc_context>(g).components;}}
1010
#endif

cp-algo/min/number_theory/euler.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
#define CP_ALGO_NUMBER_THEORY_EULER_HPP
33
#include "factorize.hpp"
44
#include "../util/big_alloc.hpp"
5-
namespace cp_algo::math{auto euler_phi(auto m){auto primes=to<big_vector>(factorize(m));std::ranges::sort(primes);auto[from,to]=std::ranges::unique(primes);primes.erase(from,to);auto ans=m;for(auto it:primes){ans-=ans/it;}return ans;}template<modint_type base>auto period(base x){auto ans=euler_phi(base::mod());base x0=bpow(x,ans);for(auto t:factorize(ans)){while(ans%t==0&&x0*bpow(x,ans/t)==x0){ans/=t;}}return ans;}template<typename _Int>_Int primitive_root(_Int p){using Int=std::make_signed_t<_Int>;using base=dynamic_modint<Int>;return base::with_mod(p,[p](){base t=1;while(period(t)!=p-1){t=random::rng();}return t.getr();});}}
5+
namespace cp_algo::math{auto euler_phi(auto m){using T=std::decay_t<decltype(m)>;auto primes=to<big_vector<T>>(factorize(m));std::ranges::sort(primes);auto[from,to]=std::ranges::unique(primes);primes.erase(from,to);auto ans=m;for(auto it:primes){ans-=ans/it;}return ans;}template<modint_type base>auto period(base x){auto ans=euler_phi(base::mod());base x0=bpow(x,ans);for(auto t:factorize(ans)){while(ans%t==0&&x0*bpow(x,ans/t)==x0){ans/=t;}}return ans;}template<typename _Int>_Int primitive_root(_Int p){using Int=std::make_signed_t<_Int>;using base=dynamic_modint<Int>;return base::with_mod(p,[p](){base t=1;while(period(t)!=p-1){t=random::rng();}return t.getr();});}}
66
#endif

0 commit comments

Comments
 (0)