1

你知道一些算法(比蛮力更好),它可以在图中找到被一个顶点分开并且彼此之间没有连接的顶点。例子:

图表示例

在此图中找到的路径将是:

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

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

4

3 回答 3

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)额外空间的算法。

于 2012-11-10T13:44:32.523 回答
1

这个问题的一个简单而直观的解决方案在于邻接矩阵。我们知道,邻接矩阵的 n 次方的第 (i,j) 个元素列出了 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)。

于 2012-11-10T14:04:49.220 回答
0

您可以使用经过改编的Warshall 算法版本来做到这一点。以下代码示例中的算法使用图形的邻接矩阵并打印i j是否存在从 to 的边和从ito的k边,但没有直接的方式 from to 。kjij

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

您可以在线查看结果。

于 2013-06-24T21:51:51.000 回答