Connected components

Splits a graph into its connected pieces, the groups of vertices joined to each other by some path, with one search per piece.

Time complexity O(V+E), gograph function gograph.ConnectedComponents.

connectivity.ConnectedComponents returns the same components, because it calls gograph.ConnectedComponents.

How it works

Two vertices are in the same connected component when some path joins them. The components are the separate pieces of a graph: no edge runs between two of them, so nothing in one piece can reach anything in another.

gograph searches breadth-first from the first vertex and gives every vertex it reaches the same component. When that search runs out, it starts the next one at the first vertex no search has reached, and so on, so the components come out in the order of their first vertex. Every vertex and edge is looked at once, so it costs O(V+E).

On a directed graph, gograph ignores the edge directions and returns the weakly connected components. It joins the two ends of each edge with union-find instead of searching, since a vertex doesn't keep a list of the edges that end at it. To find the groups that can reach each other along the edge directions, use Tarjan, Kosaraju or Gabow. Use connected components to find the islands of a network after an outage, or to handle each piece of a graph on its own.

Campus outage

The campus network while the core switches A1 and A2 are down for maintenance. Each building keeps its own switches, and the two pairs of buildings with a direct link still reach each other, but nothing else does.

An undirected graph with 98 vertices and 91 edges.

While both core switches are down, which buildings can still talk to each other?

The graph falls into 9 connected components, with 7, 7, 14, 20, 10, 10, 8, 16 and 6 vertices. No edge joins two of them, so each vertex can reach only the vertices in its own component.

Step by step

  1. ConnectedComponents searches breadth-first from each vertex no earlier search has reached, in the graph's vertex order. Every vertex a search reaches is in the same component as the vertex it started from. When the queue runs out, the component is complete.
  2. Start component 1 at A3, the first vertex. Put it in the queue.
  3. Take A3 from the front of the queue. Its neighbors A5, A6, A7, A8, A9 and A10 are new, so they join the back of the queue.
  4. Take A5 from the front of the queue. Every neighbor it has is already in the component.
  5. Take A6 from the front of the queue. Every neighbor it has is already in the component.
  6. Take A7 from the front of the queue. Every neighbor it has is already in the component.

111 more steps lead to the last one:

  1. Done. ConnectedComponents found 9 components. They come out in the order of their first vertex. Every vertex now shows the component it belongs to.

Use it in Go

for _, component := range gograph.ConnectedComponents(g) {
	var names []string
	for _, v := range component {
		names = append(names, v.Label())
	}
	fmt.Println(strings.Join(names, ", "))
}

Example graphs

More in Connectivity

  • Tarjan: Finds the strongly connected components of a directed graph, the groups of vertices that can all reach each other, with one depth-first search.
  • Kosaraju: Finds the strongly connected components of a directed graph with two depth-first searches, the second on the graph with every edge reversed.
  • Gabow: Finds the strongly connected components of a directed graph with one depth-first search and two stacks, without the lowlink values of Tarjan's algorithm.
  • Condensation: Replaces each strongly connected component with one vertex. What is left is a DAG, so it can be sorted and scheduled.
  • Cycle detection: Says whether a graph has a cycle, a way to follow its edges from a vertex back to the same vertex, and stops at the first one it finds.

All algorithms