Для неориентированных графов это можно сделать за O (n) раз с помощью простой DFS.Вот как:
Определите explore
как процедуру, которая находит все узлы, которые могут быть достигнуты из данного узла.Это просто рекурсивная DFS-подобная процедура, где на каждом узле вы находите все дочерние элементы этого узла и помещаете их в стек.
Чтобы найти ответ, запустите DFS на любом узле и запустите процедуру explore
на этом узле.Сохраните целое число (скажем, cc
) и передайте его процедуре explore
каждый раз, когда она вызывается.Кроме того, сохраните хэш-карту / словарь или такой, который отображает cc
на соответствующий узел.На каждом уровне процедуры explore
сопоставьте текущий узел с cc
на данный момент.Каждый раз, когда процедура исследования вызывается рекурсивно, передайте ей одно и то же значение cc
.
Каждый раз, когда explore
возвращается в цикл DFS, увеличивайте cc
и передайте это значение в следующий раз.Как только вы закончите со всей DFS, у вас будет словарь, который сопоставляет каждый узел с соответствующим номером подключенного компонента.Значение cc
в конце этой процедуры может дать вам количество подключенных компонентов, которые есть на графике.
Вот псевдокод:
function explore(node, graph, cc, map){
map(currentNode) = cc
//find all children of current node, and push onto stack.
//mark current node as visited
for i in stack:
explore(i, graph, cc, map)
}
function DFS{
int cc = -1
for node in keysOfGraph:
if not visited:
cc++
explore(node, graph, cc, map)
return cc
}
Из Алгоритмы Дасгупты (раздел 3.2.3)