我已经看到了Kragers min cut算法中边缘收缩的一种实现:
我们使用邻接将无向图表示为对称有向图 列表表示。
(STATMENT)每个顶点都有一个双向链接的边列表 它和指向列表开头和结尾的指针。表示边u,v 通过两个弧,(u,v)和(v,u)。这些弧线互相指向。
arc(u,v)出现在u的邻接列表中,并且有一个指向v的指针。
删除u的邻接列表中的自循环。这需要O(d(u)+ d(v))时间。
我无法理解在第一步中替换反向弧(w,v)以及它的意思(STATEMENT)?我只熟悉c语言,所以请仅参考C
答案 0 :(得分:0)
具体而言,我们有一个像
这样的结构struct Arc {
struct Arc *sym;
struct Arc *onext;
int edge;
int org;
};
。每个无向边缘表示为两个弧,每个方向一个。 edge
成员存储边缘的ID。 sym
成员指向同一边的另一个弧。 org
成员是弧的原点顶点的ID(因此边缘位于->org
和->sym->org
之间。)onext
成员指向下一个弧与相同的原点顶点;这些弧线循环连接在一起。
对于像
这样非常简单的图表 4 5
1 --- 2 --- 3
,我们有这样的结构。
struct Arc a12, a21, a23, a32;
a12.sym = &a21;
a12.onext = &a12;
a12.edge = 4;
a12.org = 1;
a21.sym = &a12;
a21.onext = &a23;
a21.edge = 4;
a21.org = 2;
a23.sym = &a32;
a23.onext = &a21;
a23.edge = 5;
a23.org = 2;
a32.sym = &a23;
a32.onext = &a32;
a32.edge = 5;
a32.org = 3;
现在让我们完成这些步骤。
让我们struct Arc *a
成为我们收缩的边缘之一。我们有像
struct Arc *b = a;
do {
b->org = a->sym->org;
b = b->onext;
} while (b != a);
浏览a->org
的邻接列表。对于我们遇到的每个弧,我们必须将原点顶点更新为a->sym->org
。
我们必须将涉及a
和a->sym
的周期拼接在一起。这是通过像(UNTESTED!)
struct Arc *temp = a->onext;
a->onext = a->sym->onext;
a->sym->onext = temp;
这超出了我所描述的代表范围。
我们像以前一样遍历邻接列表,但这一次,我们必须更加小心,因为我们正在改变它。基本循环看起来很相似。
struct Arc *b = a;
/* look for a non-self-loop */
do {
if (b->sym->org != b->org) {
a = b;
goto found;
}
b = b->onext;
} while (b != a);
/* everything is a self-loop; time to terminate the algorithm */
return;
found:
do {
if (b->onext->sym->org == b->onext->org) {
/* splice out b->onext */
b->onext = b->onext->onext;
} else {
/* go to the next arc */
b = b->onext;
}
} while (b != a);
请注意,所有此代码均为 UNTESTED 。 a
将保留具有相同原点的未删除弧。