Поиск вершин в графе, разделенных одной вершиной

Знаете ли вы какой-нибудь алгоритм (лучше, чем грубая сила), который может находить вершины в графе, которые разделены одной вершиной и не связаны между собой. Пример:

пример графика

На этом графике найдены пути:

  • 1 — 4
  • 2 — 4
  • 3 — 5

Лучшим был бы код на С ++, который использует массив списков stl в качестве представления графа, но код на любом другом процедурном языке или псевдокоде также подойдет.

1

Решение

Один из способов будет основан на поиске в ширину, где для каждой вершины i на графике мы сканируем вершины, смежные с вершинами, смежными с i (то есть два уровня смежности!).

mark = array[0..n-1] of 0
flag = 1

for i = nodes in graph do

// mark pattern of nodes adjacent to i
mark[i] = flag
for j = nodes adjacent to i do
mark[j] = flag
endfor

// scan nodes adjacent to those adjacent to i
// (separated by one vertex!)
for j = nodes adjacent to i do
for k = nodes adjacent to j do
if mark[k] != flag  and k > i then
// i,k are separated by another vertex
// and there is no edge i,k

// prevent duplicates
mark[k] = flag
endif
endfor
endfor

// implicit unmarking of current pattern
flag += 1

endfor

Если бы граф имел m ребер на вершину, это было бы O(n * m^2) алгоритм, который требует O(n) дополнительное пространство

1

Другие решения

Одно простое и интуитивно понятное решение этой проблемы заключается в матрице смежности. Как мы знаем, (i, j) -й элемент n-й степени матрицы смежности перечисляет все пути длины ровно n между i и j.
Поэтому я просто читаю в A матрицу смежности, а затем вычисляю A ^ 2. Наконец, я перечисляю все пары, которые имеют ровно один путь длины 2 между ними.

//sg
#include<stdio.h>
#define MAX_NODE 10
int main()
{
int a[MAX_NODE][MAX_NODE],c[MAX_NODE][MAX_NODE];
int i,j,k,n;
printf("Enter the number of nodes : ");
scanf("%d",&n);
for(i=0;i<n;i++)
for(j=0;j<=i;j++)
{
printf("Edge from %d to %d (1 yes/0 no) ? : ",i+1,j+1);
scanf("%d",&a[i][j]);
a[j][i]=a[i][j]; //undirected graph
}
//dump the graph
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
c[i][j]=0;
printf("%d",a[i][j]);
}
printf("\n");
}
printf("\n");

//multiply
for(i=0;i<n;i++)
for(j=0;j<n;j++)
for(k=0;k<n;k++)
{
c[i][j]+=a[i][k]*a[k][j];
}
//result of the multiplication
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d",c[i][j]);
}
printf("\n");
}
for(i=0;i<n;i++)
for(j=0;j<=i;j++)
{
if(c[i][j]==1&&(!a[i][j])&&(i!=j)) //list the paths
{
printf("\n%d - %d",i+1, j+1 );

}
}
return 0;
}

Пробный прогон для вашего графика

[aman@aman c]$ ./Adjacency2
Enter the number of nodes : 5
Edge from 1 to 1 (1 yes/0 no) ? : 0
Edge from 2 to 1 (1 yes/0 no) ? : 1
Edge from 2 to 2 (1 yes/0 no) ? : 0
Edge from 3 to 1 (1 yes/0 no) ? : 1
Edge from 3 to 2 (1 yes/0 no) ? : 1
Edge from 3 to 3 (1 yes/0 no) ? : 0
Edge from 4 to 1 (1 yes/0 no) ? : 0
Edge from 4 to 2 (1 yes/0 no) ? : 0
Edge from 4 to 3 (1 yes/0 no) ? : 1
Edge from 4 to 4 (1 yes/0 no) ? : 0
Edge from 5 to 1 (1 yes/0 no) ? : 0
Edge from 5 to 2 (1 yes/0 no) ? : 0
Edge from 5 to 3 (1 yes/0 no) ? : 0
Edge from 5 to 4 (1 yes/0 no) ? : 1
Edge from 5 to 5 (1 yes/0 no) ? : 0
01100
10100
11010
00101
00010

21110
12110
11301
11020
00101

4 - 1
4 - 2
5 - 3

Анализ
Для n вершин:

  • Время: O (n ^ 3). Может быть уменьшено до O (N ^ 2,32), что очень хорошо

  • Пробел: O (n ^ 2).

1

Вы можете сделать это с адаптированной версией Алгоритм Варшалла. Алгоритм в следующем примере кода использует матрицу смежности вашего графа и печатает i j если там
это край от i в k и край от k в j но нет прямого пути от i в j,

#include <iostream>

int main() {
// Adjacency Matrix of your graph
const int n = 5;
bool d[n][n] = {
{ 0, 1, 1, 0, 0 },
{ 0, 0, 1, 0, 0 },
{ 0, 0, 0, 1, 0 },
{ 0, 0, 0, 0, 1 },
{ 0, 0, 0, 0, 0 },
};

// Modified Warshall Algorithm
for (int k = 0; k < n; k++)
for (int i = 0; i < n; i++)
if (d[i][k])
for (int j = 0; j < n; j++)
if (d[k][j] && !d[i][j])
std::cout << i + 1 << " " j + 1 << std::endl;
}

Вы можете просмотреть результат онлайн.

0
По вопросам рекламы [email protected]