@@ -43,8 +43,13 @@ namespace lemon {
4343
4444 mutable std::vector<std::vector<Arc>> _in_arcs; // _in_arcs[node] = incoming arc IDs
4545 mutable bool _in_arcs_built;
46+
47+ // Position tracking for O(1) iteration
48+ mutable std::vector<int64_t > _arc_to_out_pos; // _arc_to_out_pos[arc_id] = position in _arc_ids
49+ mutable std::vector<int64_t > _arc_to_in_pos; // _arc_to_in_pos[arc_id] = position in _in_arcs[target]
50+ mutable bool _position_maps_built;
4651
47- SparseBipartiteDigraphBase () : _node_num(0 ), _arc_num(0 ), _n1(0 ), _n2(0 ), _in_arcs_built(false ) {}
52+ SparseBipartiteDigraphBase () : _node_num(0 ), _arc_num(0 ), _n1(0 ), _n2(0 ), _in_arcs_built(false ), _position_maps_built( false ) {}
4853
4954 void construct (int n1, int n2) {
5055 _node_num = n1 + n2;
@@ -58,6 +63,9 @@ namespace lemon {
5863 _arc_ids.clear ();
5964 _in_arcs.clear ();
6065 _in_arcs_built = false ;
66+ _arc_to_out_pos.clear ();
67+ _arc_to_in_pos.clear ();
68+ _position_maps_built = false ;
6169 }
6270
6371 void build_in_arcs () const {
@@ -72,6 +80,31 @@ namespace lemon {
7280
7381 _in_arcs_built = true ;
7482 }
83+
84+ void build_position_maps () const {
85+ if (_position_maps_built) return ;
86+
87+ _arc_to_out_pos.resize (_arc_num);
88+ _arc_to_in_pos.resize (_arc_num);
89+
90+ // Build outgoing arc position map from CSR structure
91+ for (int64_t pos = 0 ; pos < _arc_num; ++pos) {
92+ Arc arc_id = _arc_ids[pos];
93+ _arc_to_out_pos[arc_id] = pos;
94+ }
95+
96+ // Build incoming arc position map
97+ build_in_arcs ();
98+ for (Node node = 0 ; node < _node_num; ++node) {
99+ const std::vector<Arc>& in = _in_arcs[node];
100+ for (size_t pos = 0 ; pos < in.size (); ++pos) {
101+ Arc arc_id = in[pos];
102+ _arc_to_in_pos[arc_id] = pos;
103+ }
104+ }
105+
106+ _position_maps_built = true ;
107+ }
75108
76109 public:
77110
@@ -212,18 +245,14 @@ namespace lemon {
212245
213246 void nextOut (Arc& arc) const {
214247 if (arc < 0 ) return ;
215-
248+
249+ build_position_maps ();
250+
251+ int64_t pos = _arc_to_out_pos[arc];
216252 Node src = _arc_sources[arc];
217- int64_t start = _row_ptr[src];
218253 int64_t end = _row_ptr[src + 1 ];
219-
220- for (int64_t i = start; i < end; ++i) {
221- if (_arc_ids[i] == arc) {
222- arc = (i + 1 < end) ? _arc_ids[i + 1 ] : Arc (-1 );
223- return ;
224- }
225- }
226- arc = -1 ;
254+
255+ arc = (pos + 1 < end) ? _arc_ids[pos + 1 ] : Arc (-1 );
227256 }
228257
229258 void firstIn (Arc& arc, const Node& node) const {
@@ -240,18 +269,14 @@ namespace lemon {
240269
241270 void nextIn (Arc& arc) const {
242271 if (arc < 0 ) return ;
243-
272+
273+ build_position_maps ();
274+
275+ int64_t pos = _arc_to_in_pos[arc];
244276 Node tgt = _arc_targets[arc];
245277 const std::vector<Arc>& in = _in_arcs[tgt];
246-
247- // Find current arc in the list and return next one
248- for (size_t i = 0 ; i < in.size (); ++i) {
249- if (in[i] == arc) {
250- arc = (i + 1 < in.size ()) ? in[i + 1 ] : Arc (-1 );
251- return ;
252- }
253- }
254- arc = -1 ;
278+
279+ arc = (pos + 1 < in.size ()) ? in[pos + 1 ] : Arc (-1 );
255280 }
256281 };
257282
0 commit comments