关于java:如何检查两个顶点之间的图形连接

How to check graph connectivity between two vertices

我正在尝试实现一种遗传算法来找到一组边缘,这些边缘的删除将断开图的连接。更具体地说,我使用的是由顶点和边组成的有向非循环图。每边都有成本或重量。遗传算法生成大量的集合C(即在两个顶点之间选择一些边)。现在我的问题是检查这组边是否代表一个切割集,或者断开图形。然后,遗传算法寻找包含在切割集中的可能的最小边缘成本总和。

所以,我使用了一种叫做连接图测试的方法,它是从一个"图形算法和优化的Java库"来测试连通性的。这对我不起作用,因为它只扫描顶点的邻居。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
public static boolean isConnected(Individual ind)
{
    int n= Settings.numOfNodes;
    int m= Settings.numOfEdges-ind.cutSet.size();
    int nodei[]= new int[m+1];
    int nodej[]= new int[m+1];

    int tempi[]= new int[m];
    int tempj[]= new int[m];

    int[] temp= (int[])Settings.nodei.clone();

    for(int edg:ind.cutSet)
        temp[edg]= -1;

        int count=0;
        for(int i=0; i<Settings.numOfEdges; i++)
    {
       if(temp[i]!=-1)
      {
        tempi[count]=Settings.nodei[i];
        tempj[count]=Settings.nodej[i];            
        count++;
      }
   }
    nodei[0]=0;
    nodej[0]=0;
    for(int i=0; i<tempi.length;i++)
       {
          nodei[i+1]=tempi[i];
          nodej[i+1]=tempj[i];
       }



    int i,j,k,r,connect;
    int neighbor[] = new int[m + m + 1];
    int degree[] = new int[n + 1];
    int index[] = new int[n + 2];
    int aux1[] = new int[n + 1];
    int aux2[] = new int[n + 1];
    for (i=1; i<=n; i++)
    degree[i] = 0;
    for (j=1; j<=m; j++) {
         degree[nodei[j]]++;
         degree[nodej[j]]++;
    }
    index[1] = 1;
    for (i=1; i<=n; i++) {
        index[i+1] = index[i] + degree[i];
        degree[i] = 0;
    }
    for (j=1; j<=m; j++) {
        neighbor[index[nodei[j]] + degree[nodei[j]]] = nodej[j];
        degree[nodei[j]]++;
        neighbor[index[nodej[j]] + degree[nodej[j]]] = nodei[j];
        degree[nodej[j]]++;
    }
    for (i=2; i<=n; i++)
         aux1[i] = 1;
         aux1[1] = 0;
         connect = 1;
         aux2[1] = 1;
         k = 1;
         while (true) {
              i = aux2[k];
              k--;
              for (j=index[i]; j<=index[i+1]-1; j++) {
                    r = neighbor[j];
                    if (aux1[r] != 0) {
                       connect++;
                    if (connect == n) {
                       connect /= n;
                    if (connect == 1) return true;
                       return false;
                    }
                    aux1[r] = 0;
                    k++;
               aux2[k] = r;
         }
    }
        if (k == 0) {

    connect /= n;
    if (connect == 1) return true;
    return false;
    }
    }
  }

给定以下有向非循环图:

1
2
3
4
5
6
7
number of vertices = 4
number of edges = 5
1->2
1->3
1->4
2->4
3->4

如果我们去除以下边缘:

1
2
3
1->2
1->3
2->4

然后,该方法返回该图在以下路径之间仍有路径时断开连接:

1
1->4

我正在寻找一种算法或方法来检查是否删除了一些边,这个图仍然连接在开始和目标顶点之间。换言之,图形在这两个顶点之间仍然存在一些其他路径。

一个有效集合的示例,当移除该图时,该集合未连接:

1
2
3
1->2
1->3
1->4

1
2
3
2->4
1->4
3->4

拜托,我愿意接受任何解决这个问题的想法。

谢谢


正在检查连接:

您的图是有向A循环的,因此您可以预先处理并找到Paths = { (u,v) | there is a path from u to v }

在删除/添加每个边缘(u,v)之后,您需要做的就是相应地重置Paths。注意,对于每个v'(u,v')Paths中,前提是且仅当存在u'时,(u,u')在您的图形中仍然是一个边,(u',v')Paths中。别忘了递归地调用Paths修改每个u的父代。尽管在最坏的情况下,这个解决方案并不比BFS更好,但在一般情况下,它应该更好——因为在每次更改之后,您不需要探索整个图表。

编辑:示例例如,在您的图形中,Path={(1,2),(1,3),(1,4),(2,4),(3,4)}—除了2到3之外,还有一条到所有"正向"顶点的路径。现在,如果去掉(1,4),你得到Path={(1,2),(1,3),(1,4),(2,4),(3,4)},注意(1,4)仍然在里面,因为Path中有边(1,2)和(2,4)。现在取下(2,4),结果是:Path={(1,2),(1,3),(1,4),(3,4)}。同样,由于(1,3)仍然是边缘,(3,4)仍在Path中,所以(1,4)仍然存在。现在取下(3,4)。没有从34的路径,所以您删除(3,4)。现在,递归地修改3的所有父级。由于13的亲本,你可以向他求证,你发现(1,u)的边缘已经没有了,以致(u,4)仍在运行中,所以我们把它从Path中删除,结果产生Path={(1,2),(1,3)}

查找要删除的边集:

我将从移除所有边开始,添加边,而不是移除它们。只能添加不使图形连接的边。使用这种方法,可以尝试最大化添加的边的值,而不是最小化删除的边。通过这样做-您可以确保您的解决方案是可行的,并且图形确实没有连接。