Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Graph In-degree Calculation from Adjacency-list

I came across this question in which it was required to calculate in-degree of each node of a graph from its adjacency list representation.

for each u
   for each Adj[i] where i!=u
     if (i,u) ∈ E
         in-degree[u]+=1

Now according to me its time complexity should be O(|V||E|+|V|^2) but the solution I referred instead described it to be equal to O(|V||E|).

Please help and tell me which one is correct.

like image 201
silentseeker Avatar asked Apr 08 '14 07:04

silentseeker


2 Answers

Rather than O(|V||E|), the complexity of computing indegrees is O(|E|). Let us consider the following pseudocode for computing indegrees of each node:

for each u
  indegree[u] = 0;

for each u
  for each v \in Adj[u]
    indegree[v]++;

First loop has linear complexity O(|V|). For the second part: for each v, the innermost loop executes at most |E| times, while the outermost loop executes |V| times. Therefore the second part appears to have complexity O(|V||E|). In fact, the code executes an operation once for each edge, so a more accurate complexity is O(|E|).

like image 77
Corneliu Avatar answered Nov 15 '22 10:11

Corneliu


According to http://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)Graphs.html, Section 4.2, with an adjacency list representation,

Finding predecessors of a node u is extremely expensive, requiring looking through every list of every node in time O(n+m), where m is the total number of edges.

So, in the notation used here, the time complexity of computing the in-degree of a node is O(|V| + |E|).

This can be reduced at the cost of additional space of using extra space, however. The Wiki also states that

adding a second copy of the graph with reversed edges lets us find all predecessors of u in O(d-(u)) time, where d-(u) is u's in-degree.

An example of a package which implements this approach is the Python package Networkx. As you can see from the constructor of the DiGraph object for directional graphs, networkx keeps track of both self._succ and self._pred, which are dictionaries representing the successors and predecessors of each node, respectively. This allows it to compute each node's in_degree efficiently.

like image 32
Kurt Peek Avatar answered Nov 15 '22 08:11

Kurt Peek