我正在尝试实现遗传算法来找到一组边缘,其移除将断开图形。更具体地说,我使用的是由顶点和边组成的有向无环图。每个边缘都有成本或重量。 遗传算法产生许多集合C(即,选择两个顶点之间的一些边缘)。现在我的问题是检查这组边缘是代表切割集还是断开图形。然后,遗传算法正在寻找切割集中包括的可能的最小边缘成本总和。
因此,我使用了一种名为Connected Graph Testing的方法,该方法取自“图形算法和优化的Java库”一书来测试连通性。这对我不起作用,因为它只扫描顶点的邻居。
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;
}
}
}
给出以下有向无环图:
number of vertices = 4
number of edges = 5
1->2
1->3
1->4
2->4
3->4
如果我们删除以下边缘:
1->2
1->3
2->4
然后,该方法返回断开此图形,同时在:
之间仍有路径1->4
我正在寻找一种算法或方法来检查我们是否删除了一些边缘,图形仍然连接在起点和目标顶点之间。换句话说,图形在这两个顶点之间仍然存在一些其他路径。
有效集合的示例,在删除图表时未连接:
1->2
1->3
1->4
或
2->4
1->4
3->4
拜托,我愿意接受解决这个问题的任何想法或想法。
谢谢
答案 0 :(得分:1)
您的图表是定向的,因此您可以预处理并查找Paths = { (u,v) | there is a path from u to v }
。
删除/添加每个边(u,v)
后,您需要做的就是相应地重置Paths
。请注意,对于每个v'
,(u,v')
位于Paths
当且仅当存在u'
时,(u,u')
仍然是图表中的边缘,{ {1}}位于(u',v')
。
不要忘记以递归方式递归调用每个Paths
父项的Paths
修改。
虽然这个解决方案在最坏的情况下并不比BFS好,但在平均情况下它应该更好 - 因为你不需要在每次改变后探索整个图形。
编辑:示例
例如,在图形中,u
- 除了从2到3之外,所有顶点到所有“前向”顶点都有一条路径。
现在,如果你删除边Path={(1,2),(1,3),(1,4),(2,4),(3,4)}
,你会(1,4)
注意Path={(1,2),(1,3),(1,4),(2,4),(3,4)}
仍在那里,因为有边(1,2)和(2,4)是在(1,4)
。
现在删除Path
,结果为:(2,4)
。同样,Path={(1,2),(1,3),(1,4),(3,4)}
仍然存在,因为(1,4)
仍然是边缘而(1,3)
位于(3,4)
。
现在删除Path
。从(3,4)
到3
没有剩余路径,因此您删除了4
。现在,递归修改所有(3,4)
的父母。由于3
是1
的父级,因此在他身上调用它,您发现没有更多边3
,因此(1,u)
仍在路径中,因此我们删除来自(u,4)
,结果为Path
。
我从删除所有边开始,然后添加边,而不是删除它们。您只能添加不使图形连接的边。使用这种方法,您尝试最大化您添加的边缘值,而不是最小化您删除的边缘。
通过这样做 - 您确保您的解决方案可行,并且图表确实没有连接。