查找图中由一个顶点分隔的顶点

时间:2012-11-10 12:11:52

标签: c++ algorithm graph vertex

你知道一些算法(优于强力),它可以在图中找到由一个顶点分隔并且彼此之间没有连接的顶点。例如:

graph example

在此图表中找到的路径为:

  • 1 - 4
  • 2 - 4
  • 3 - 5

最好的是c ++代码,它使用stl列表数组作为图形表示,但任何其他过程语言或伪代码中的代码也可以。

3 个答案:

答案 0 :(得分: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 :(得分:1)

这个问题的一个简单直观的解决方案在于邻接矩阵。我们知道,(i,j)邻接矩阵的第n个幂的元素列出了i和j之间的所有长度n的路径。
所以我只读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)。

答案 2 :(得分:0)

您可以使用Warshall's algorithm的改编版本执行此操作。以下代码示例中的算法使用图形的邻接矩阵,如果存在则打印i j 是从ik的边缘,从kj的边缘,但没有从ij的直接路径。

#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;
}

您可以查看结果online