Учитывая минимальное остовное дерево M = { V , E } и ребро (i,j)
, пусть L = { V L , E L } и R = { V R , E R } - два подграфа (дерева), созданные путем удаления ребра (i,j)
из M .Край (i,j)
будет пересекаться только путями (u,v)
, где u
находится в L , а v
находится в R (или наоборот).Поскольку все вершины в L связаны со всеми вершинами в R , а все пути от вершины u
до вершины v
являются уникальными, число раз, когда ребро (i,j)
равноперечеркнуто: | V L | × | V R |.
Найти количество вершин на одномна стороне каждого ребра все, что требуется, - это один обход в глубину, начинающийся с произвольного узла, возвращающий nodeCount
, который является суммой nodeCount
для каждого дочернего элемента + 1 для текущего узла.Следовательно, nodeCount
для конечных узлов равно 1.
Родительская вершина удаляется из списка смежности, переданного в рекурсивных вызовах ее дочерних узлов, чтобы узлы не учитывались несколько раз.
Таким образом, если мы достигли вершины p из вершины R , как показано в этом подграфе,
R
|
|
p
/ \
/ \
c1 c2
nodeCount
, возвращенный в R , будетбыть 1 + nodeCount(c1) + nodeCount(c2)
.Если оба c1 и c2 являются конечными узлами, возвращаемое значение nodeCount
будет равно 3.
В конце этого процесса каждое из значений nodeCount
возвращается число узлов на стороне одна соответствующего ребра.Число узлов на другой стороне этого ребра будет определяться как N - nodeCount
, где N
- количество вершин в MST.Число путей через этот край будет
nodeCount * (N - nodeCount)
Вот некоторый псевдокод, который, надеюсь, немного прояснит ситуацию:
CountNodes(A, r)
// Given adjacency matrix A, returns the number of nodes
// reachable from node r (including r itself)
nodeCount = 1 // include root node in count
// rows/columns in A for visited nodes should be all 0
// so that we don't count this node multiple times
// update node r as visited before recursive call to CountNodes
A[r,] = 0
A[,r] = 0
if the number of unvisited children of r is 0
return nodeCount // r is a leaf, nodeCount = 1
end if
for each node c connected to r
// get count of nodes in subtree rooted at c
childCount = CountNodes(A, c)
PRINT (r,c) = childCount // display count for current edge
nodeCount = nodeCount + childCount // update count to report to parent
end for
return nodeCount
end CountNodes
Как я уже сказал, для начального вызова мы используем произвольныйузел.Неважно, какой из них мы используем, так как все ответы будут эквивалентны (правильный счет с одной стороны каждого края, хотя не обязательно с той же стороной).При первоначальном вызове неявно генерируется фиктивная вершина в качестве родителя первого узла, поэтому nodeCount
, возвращаемое в конце, равно N , числу вершин в MST.
Вот примерная матрица смежности для 10 вершин и вывод из функции при запуске с вершины 0:
A =
0 1 0 0 0 0 0 0 0 0
1 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 1 0 0 0
0 1 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 1 1
0 0 0 1 0 0 0 1 1 0
0 0 0 0 1 0 1 0 0 0
0 0 1 0 0 1 1 0 0 0
0 0 0 0 0 1 0 0 0 0
(6,3) = 1
(8,2) = 1
(5,9) = 1
(8,5) = 2
(6,8) = 4
(7,6) = 6
(4,7) = 7
(1,4) = 8
(0,1) = 9
return = 10
Поскольку nodeCount
для ребра (6,8)
равно 4
, количество путей, проходящих через ребро(6,8)
- это 4 * (10 - 4) = 24
.Количество путей через ребро (0,1)
будет 9