Codeforces celebrates 10 years! We are pleased to announce the crowdfunding-campaign. Congratulate us by the link https://codeforces.com/10years. ×

Graph saving methods

Revision en5, by Arpa, 2017-06-04 13:37:16

Hi.

## Introduction.

We have a graph, we want to save it (and maybe run DFS on it for example); simple? Yes, but I want to show different methods for this, you can choose any of them depending on problem.

Simple, if graph is not weighted, save in G[v][u] if there is an edge between v and u or not.

If graph is weighted, if there is an edge between v and u save it’s weight in G[v][u], save  - 1 otherwise (if weight can be negative, use inf instead of  - 1).

Memory usage : .
Overall time complexity : (for running dfs).

Code here

### Vectors.

It's the most common method for saving graph. For each vertex keep a vector of it’s edges, now for each edge just save it in related vectors. Use pair (or another struct) for saving weighted graph. It works similar for directed graph.

Memory usage : (Note that vector uses more memory than you need).
Overall time complexity : (for running dfs).

Code here
##### Dynamic array.

This method is rarely used. For each vertex count edges connected to it at first, then allocate a enough space for each vertex to save it’s adjacency-list. Note that this method is Offline.

Memory usage : .
Overall time complexity : (for running dfs).

Code here

This method is used when id of edges are important and works only for directed graphs (or if you can convert the undirected graph to directed). We use array for saving edges. Then, for each vertex we keep index of last added edge and for each edge consider it’s from Fromi to Toi, we keep the index of last edge before this edge that Fromindex = Fromi and name it prvi. Then we can use headv and prv array to find adjacency-list.

Memory usage : .
Overall time complexity : (for running dfs).

Code here

Application: Solving flow network problems. Wikipedia: Maximum flow problem.

Naive implementation
Dinic’s blocking flow algorithm

Usage of this method in above codes are where we use cap[e] -= x, cap[e ^ 1] += x. Because of special adding edge method, it is guaranteed that if edge e is from v to u, is its pair and it’s from u to v.

Related submission : 23115110.

### Index keeping.

This method is used when index of edges is important (i.e. in queries we need to change something about edges, i.e. change weight, delete edge). Keep index of edges related to each vertex in its vector, and for each edge keep the vertices connecting with this edge (see code below).

Note that index keeping is possible and maybe easier using map (or unordered_map), but it is faster using this method. Also note that dynamic array method could be used here as well.

Memory usage : (Note that vector uses more memory than you need).
Overall time complexity : (for running dfs).

Code here

Example: Consider you need to change weight of edges online, this is simple using index keeping method, but it isn’t possible with other methods (at least it will be harder). Related submission : 20776118.

Application: Finding Euler tour. Wikipedia : Eulerian path. Blocking edges is easier with this method, that’s what we need in Euler tour finding. Related submissions : 21395473, 21636007.

## Comparison.

I used Codeforces polygon for comparing and generated 16 random graphs:

• #1 to #4 : n = 106, m = 106

• #5 to #4 : n = 105, m = 106

• #9 to #8 : n = 104, m = 106

• #13 to #16 : n = 103, m = 106

# dynamic array linked list vector
1 1637 / 44 1123 / 29 1606 / 39
2 1637 / 44 1247 / 29 1559 / 39
3 1590 / 44 1107 / 29 1560 / 39
4 1669 / 44 1169 / 29 1622 / 39
5 1060 / 29 1060 / 31 1169 / 36
6 1106 / 29 1045 / 31 1123 / 36
7 1060 / 30 1029 / 31 1122 / 36
8 1091 / 29 1044 / 31 1169 / 36
9 1029 / 26 1013 / 29 1044 / 29
10 982 / 26 998 / 29 1013 / 29
11 1013 / 26 982 / 29 1201 / 29
12 1123 / 26 1029 / 29 1029 / 29
13 998 / 26 951 / 29 982 / 27
14 935 / 26 982 / 29 950 / 27
15 951 / 26 951 / 29 982 / 27
16 966 / 26 1060 / 29 1013 / 27
Σ 16 16 16
max. 1669ms / 44MB 1247ms / 31MB 1622ms / 39MB

It's really strange for me that vector uses less memory than dynamic array while testing, can someone explain the reason? Here is the link to codes and generator.

UPD: I found the answer, I missed that in dynamic array method we are saving edges in pairs, and keeping the sz array in addition (thanks to ATofighi).

As usual I’d like to finish the post with a poem:

بی سبب هرگز نمی‌گردد کسی یار کسی
یار بسیار است تا گرم است بازار کسی


By: Parto biza’ee arani.

Translation: No one becomes friend with another one without reason. People are like shops, a shop is full of customers while it has goods.

P.S. Kindly write in comments (or use private chat in case of necessary) if something is wrong.

#### History

Revisions

Rev. Lang. By When Δ Comment
en5 Arpa 2017-06-04 13:37:16 2 Fixed grammar mistakes using Grammarly.
en4 Arpa 2017-03-20 16:03:24 278 answer has been found
en3 Arpa 2017-03-20 12:01:34 3821 bug in generator fixed, statistics in comparison updated.
en2 Arpa 2017-03-19 22:42:20 114 Files added.
en1 Arpa 2017-03-19 20:34:14 40134 Initial revision (published)