views:

90

answers:

3

I have an undirected unweighted graph G = (V, E) and a randomly chosen subset S of its vertices. I want to check whether the vertices in S are mutually adjacent (i.e. form a complete subgraph/a clique).

I have the following algorithm (pseudo-code):

foreach vertex in S  {
  // Check that the vertex has enough edges
  if (vertex.edges.count < S.size - 1)
    return false;

  // Check that there is an edge to each vertex in S
  foreach vertex2 in S  {
    if (!vertex.hasEdgeTo(vertex2))
      return false;
  }
}
return true;

The problem is that this algorithm's worst-case performance is O(|V|2) (in case when the subset S contains all the vertices of a complete graph).

My question is: is there a faster algorithm that runs with a better big O worst-case complexity?

+4  A: 

Assuming that you can check whether two vertices are incident in O(1), your algorithm has O(|V|²) = O(|E|) time complexity in the worst case. I don't think you can do better than O(|E|), since you should really check all the edges of the subgraph.

Bolo
Thought that... I was hoping for a nice trick that would possibly make it O(|V| log(|V|) but it seems I'll just have to stick to this one.
dark_charlie
@dark_charlie Well, while you probably can't beat the `O(|S|²)` worst-case time complexity, you can still speed up the average running time of your algorithm using a number of tricks. One that comes to mind is: ask the `x.hasEdgeTo(y)` questions in such an order that the ones most likely to fail are asked first. For example you can sort the vertices ascending by their degree (in `O(|S| log |S|)`) and execute the outer loop in that order.
Bolo
+2  A: 

I don't believe you'll get a non O(|E|^2) algorithm for performing this check. Logically, each V1-V2 edge must be sought to prove completeness. Separating into two loops, the first checking the edge counts and the second then checking the vertex connections would potentially speed up the algorithm. Perhaps another way of representing the graph (with edges rather than vertices) would help?

Will A
Good point @Bolo re: O(|V|^2).
Will A
What do you think would be the advantage of representing the graph using an edge list/set for this problem? I have no experience with such representation.
dark_charlie
+2  A: 

How does your hasEdgeTo perform? If you use a tree-based set to store the edges, that function is not just O(1).

By using a bitvector for the edges, you can go with O(|S| * min(|E|, |V|, |S|)).

Albert
hasEdgeTo is O(1), I am using an adjacency matrix. What is your idea for the O(|S| * min(log(|E|), |S|))) algorithm?
dark_charlie
@dark_charlie: Sorry, either I don't remember anymore what I have thought yesterday or it was bullshit. The len of the bitvector will be either |E| or |V| (actually, divided by 8 because you use bits). But I am still thinking if there might be another representation which makes this faster. I will write back if I got an idea or remember again. :)
Albert