使用随机收缩算法最小切割无向图

时间:2014-06-04 16:45:56

标签: c algorithm graph

我已经看到了Kragers min cut算法中边缘收缩的一种实现:

我们使用邻接将无向图表示为对称有向图 列表表示。

(STATMENT)每个顶点都有一个双向链接的边列表 它和指向列表开头和结尾的指针。表示边u,v 通过两个弧,(u,v)和(v,u)。这些弧线互相指向。

arc(u,v)出现在u的邻接列表中,并且有一个指向v的指针。

  1. 对于v的邻接列表中的每个(v,w),将反向弧(w,v)替换为 (W,U)。该操作采用O(d(v)),其中d(v)是v。
  2. 的程度
  3. 将v的弧列表附加到u的弧列表中。这需要一段时间。
  4. 从V(G)删除v。这需要一段时间。
  5. 删除u的邻接列表中的自循环。这需要O(d(u)+ d(v))时间。

    我无法理解在第一步中替换反向弧(w,v)以及它的意思(STATEMENT)?我只熟悉c语言,所以请仅参考C

  6. 解释我

1 个答案:

答案 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;

现在让我们完成这些步骤。

对于v的邻接列表中的每个(v,w),将反向弧(w,v)替换为(w,u)。

让我们struct Arc *a成为我们收缩的边缘之一。我们有像

这样的循环
struct Arc *b = a;
do {
    b->org = a->sym->org;
    b = b->onext;
} while (b != a);

浏览a->org的邻接列表。对于我们遇到的每个弧,我们必须将原点顶点更新为a->sym->org

将v的弧列表附加到u。

的弧列表中

我们必须将涉及aa->sym的周期拼接在一起。这是通过像(UNTESTED!)

这样的交换来完成的
struct Arc *temp = a->onext;
a->onext = a->sym->onext;
a->sym->onext = temp;

从V(G)

删除v

这超出了我所描述的代表范围。

删除u

的邻接列表中的自循环

我们像以前一样遍历邻接列表,但这一次,我们必须更加小心,因为我们正在改变它。基本循环看起来很相似。

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将保留具有相同原点的未删除弧。