Skip to content

Commit 889f4a5

Browse files
committed
Use edge type class
1 parent 8ddb5ed commit 889f4a5

File tree

3 files changed

+56
-24
lines changed

3 files changed

+56
-24
lines changed

cp-algo/graph/base.hpp

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,64 @@
55
#include <ranges>
66
#include <vector>
77
namespace cp_algo::graph {
8+
struct edge_base {
9+
int to;
10+
11+
edge_base() {}
12+
edge_base(int v): to(v) {}
13+
14+
static auto read(int v0 = 0) {
15+
int u, v;
16+
std::cin >> u >> v;
17+
return std::pair{u - v0, edge_base(v - v0)};
18+
}
19+
20+
edge_base backedge(int from) const {
21+
return {from};
22+
}
23+
};
24+
template<typename edge_info>
25+
concept edge_type = std::is_base_of_v<edge_base, edge_info>;
26+
827
enum type {directed = 0, undirected = 1};
9-
template<type undirected>
28+
template<type undirected, edge_type edge_info = edge_base>
1029
struct graph {
11-
graph(int n, int v0 = 0): n(n), v0(v0), adj(n) {}
30+
graph(int n, int v0 = 0): _n(n), m(0), v0(v0), adj(n) {}
1231

13-
void add_edge(int u, int v) {
14-
adj.push(u - v0, size(to));
15-
to.push_back(v - v0);
32+
void add_edge(int u, edge_info e) {
33+
m++;
34+
adj.push(u, size(edges));
35+
edges.push_back(e);
1636
if constexpr (undirected) {
17-
adj.push(v - v0, size(to));
37+
adj.push(e.to, size(edges));
1838
}
19-
to.push_back(u - v0);
39+
edges.push_back(e.backedge(u));
2040
}
2141
void read_edges(int m) {
2242
for(int i = 0; i < m; i++) {
23-
int u, v;
24-
std::cin >> u >> v;
25-
add_edge(u, v);
43+
auto [u, e] = edge_info::read(v0);
44+
add_edge(u, e);
45+
}
46+
}
47+
void call_adjacent(int v, auto &&callback, auto &&terminate = [](){return false;}) const {
48+
for(int sv = adj.head[v]; sv && !terminate(); sv = adj.next[sv]) {
49+
callback(adj.data[sv]);
2650
}
2751
}
52+
int deg(int v) const {
53+
int ans = 0;
54+
call_adjacent([&ans](){ans++;});
55+
return ans;
56+
}
2857
auto nodes_view() const {
29-
return std::views::iota(0, n);
58+
return std::views::iota(0, _n);
3059
}
31-
32-
int n, v0;
33-
std::vector<int> to;
60+
edge_info& edge(int e) {return edges[e];}
61+
edge_info const& edge(int e) const {return edges[e];}
62+
int n() const {return _n;}
63+
private:
64+
int _n, m, v0;
65+
std::vector<edge_info> edges;
3466
data_structures::stack_union<int> adj;
3567
};
3668
}

cp-algo/graph/cycle.hpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,29 @@
55
#include <vector>
66
namespace cp_algo::graph {
77
std::vector<int> find_cycle(auto const& g) {
8-
std::vector<char> state(g.n);
8+
std::vector<char> state(g.n());
99
std::vector<int> cycle;
1010
auto dfs = [&](auto &&self, int v, int pe) -> bool {
1111
state[v] = 1;
12-
for(int sv = g.adj.head[v]; sv; sv = g.adj.next[sv]) {
13-
int e = g.adj.data[sv];
12+
bool found = false;
13+
g.call_adjacent(v, [&](int e) {
1414
if(e / 2 != pe / 2) {
15-
auto u = g.to[e];
15+
int u = g.edge(e).to;
1616
if(state[u] == 0) {
1717
if(self(self, u, e)) {
18-
if(g.to[cycle[0]] != g.to[cycle.back() ^ 1]) {
18+
if(g.edge(cycle[0]).to != g.edge(cycle.back() ^ 1).to) {
1919
cycle.push_back(e);
2020
}
21-
return true;
21+
found = true;
2222
}
2323
} else if(state[u] == 1) {
2424
cycle = {e};
25-
return true;
25+
found = true;
2626
}
2727
}
28-
}
28+
}, [&found](){return found;});
2929
state[v] = 2;
30-
return false;
30+
return found;
3131
};
3232
for(int i: g.nodes_view()) {
3333
if(!state[i] && dfs(dfs, i, -2)) {

verify/graph/cycle_undirected.test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ void solve() {
1919
} else {
2020
ranges::reverse(res);
2121
cout << size(res) << "\n";
22-
for(auto it: res) {cout << g.to[it] << ' ';}
22+
for(auto it: res) {cout << g.edge(it).to << ' ';}
2323
cout << "\n";
2424
for(auto it: res) {cout << it / 2 << ' ';}
2525
cout << "\n";

0 commit comments

Comments
 (0)