CUT Stoer-Wagner Algorithm [转]

中译「割」。一个 Cut 把一张图上的点分成两群。也就是说,每一个点都必须选边站(也可以全部都站在同侧,另一侧就是空的)。以数学术语来描述:一个 Cut 把一张图上所有点所构成的集合,重新划分成两个集合

 

 

如果图上的边拥有权重,一个 Cut 也可以有权重。无向图:由第一群点横跨到第二群点的所有边的权重总和。有向图:由第一群点横跨到第二群点的所有边的权重总和,减去由第二群点横跨到第一群点的所有边的权重总和。

 

 

Cut 切断了点与点之间的连结,将一张图一分为二。各位可以想一想 Cut 可以应用在哪些地方。

 

【注:一般大家在谈 Cut 的时候,经常是使用另外一种定义: Cut 的其中一侧至少要有一点,而且图上的边的权重均非负值。我想这应该是因为 Cut 的演算法,一开始是从 Flow 的演算法推演来的。】

 

 

 

 

Minimum Cut ( Min-Cut ):

 

「最小割」。给定一张图,权重最小的 Cut 就是 Min-Cut 。一张图上可能会有许多个 Min-Cut

 

Maximum Cut ( Max-Cut ):

最大割」。给定一张图,权重最大的 Cut 就是 Max-Cut 。一张图上可能会有许多个 Max-Cut

 

 

 

 

Contraction:

「收缩」。在一个 Cut 之中,把 Cut 的其中一侧的任两点作合并,不会影响此 Cut 的权重。合并图上的点、却不影响一个 Cut 的权重,这个行为就叫做 Contraction

 

 

 

 

 

进行 Contraction 之后,甚至可以把两点之间多重的边的权重相加合并,也不会改变 Cut 的权重。

 

 

 

Maximum Adjacency Search:

在讲述 Min-Cut 的演算法之前,这里先介绍一个与 Min-Cut 极有关系的 Maximum Adjacency Search

1. 建立一个空的A集合。

2. 首先随便在图上找一个点,加入到A集合当中。

3. w(A, x)是「目前的A集合的各个点」与「x点」之间所有的边的权重总和。

    逐次加入一个尚未加入A当中、且w(A, x)最大的x点到A集合中。

4. 图上所有点都加入到A集合之后,各个点加入的顺序即为

 

 

 

 

 

Maximum Adjacency Search ( adjacency matrix ):利用 Dynamic Programming 來實做程式碼,時間複雜度是 O(V^2) 。如同 Dijkstra's Algorithm 一樣,可以另外再配合 Priority Queue ,成為 O(V+ElogE) 。

 

 

 

 

 

int map [9][9]; // adjacency matrix  
int w[9];       // 紀錄各個點到目前的A集合的距離  
bool visit[9]; // 紀錄各個點是不是已找過  

void maximum_adjacency_search()  
{  
    for (int i=0; i<9; i++) visit[i] = false; // initialize  
    for (int i=0; i<9; i++) w[i] = 0;  

    for (int i=0; i<V; ++i)  
    {  
        // 找出一個尚未加入A當中、且w(A, x)最大的x點。  
        int s = 0, max = -1e9;  
        for (int j=0; j<V; ++j)  
            if (!visit[i] && w[i] > max)  
                max = w[i], s = i;  

        visit[s] = true;    // 加入s點到A集合  
        cout << "這次讀到第" << s << "點" << endl;  

        // 加入s點到A集合後,更新w(A, x)的值。  
        for (int t=0; t<V; ++t)  
            if (!visit[t])  
                w[t] += map[s][t];  
    }  
}

 

 

 

Maximum Adjacency Search v.s. Min-Cut:

在一张无向图当中,边的权重皆非负值,令这张图经过 Maximum Adjacency Search 所得到的顺序是 x1-x2- … -xV 。在这张图中, {x1 … xV-1} {xV} 这一个 Cut ,必会是这张图「限制 xV-1 xV Cut 不同侧」的 Min-Cut

 

 

 

 

笔者曾努力想过证明,但能力不足,无法证得这个性质。如果有人懂得证明,欢迎告知。

 

 

 

Min-Cut: Stoer-Wagner Algorithm:

用来求出一张无向图的其中一个 Min-Cut 。此处提及的 Cut 其中一侧至少要有一点,而且图上的边的权重均非负值。

任取图上两点,这两点要嘛就是在 Min-Cut 同侧,要嘛就是在 Min-Cut 不同侧。这个想法等同于本站文件「 Divide and Conquer ─ Combination 」分割问题的想法。

 

如果这两点将在 Min-Cut 同侧,那么我们可以进行 Contraction ,合并这两点为一点,制作出一张比原图还要少一点的图,缩小问题范畴。这么做不会影响此两点在同侧的 Cut 们的权重,当然也就不会影响 Min-Cut 的权重。

 

如果这两点会在 Min-Cut 不同侧,则需要想办法找出这两点在不同侧的 Min-Cut

 

 

 

 

 

 

演算法:

Stoer-Wagner Algorithm 巧妙地运用了 Maximum Adjacency Search 的性质,求出一个限制某两点在不同侧的 Min-Cut

map[a][b]a点到b点的距离(即是边的权重)。

 

1. 重复下面这件事V-1次,以求出其中一侧至少要有一点的Min-Cut

 甲、Maximum Adjacency Search:对图上所有点使用Maximum Adjacency Search

   最后两点依序为s点和t点,求出s点和t点在不同侧的Min-Cut

 乙、Contraction:合并s点和t点,继续求出s点和t点在同侧的Min-Cut

   对于图上每一点xmap[s][x]=map[x][s]=map[s][x]+map[t][x](把t点并至s点)

 

 

 

 

时间复杂度:

约是 V 次的 Maximum Adjacency Search ,总共是 O((V^2) * V) = O(V^3)

 

计算 Min-Cut 的权重( adjacency matrix ):

实做方式可参考「 Shortest Path: Dijkstra's Algorithm 」。

 

 

 

 

int map[9][9]; // adjacency matrix  
int w[9];       // 紀錄各個點到目前的A集合的距離  
bool visit[9]; // 紀錄各個點是不是已找過  
bool combine[9];    // 紀錄各個點被合併過了沒  

void maximum_adjacency_search(int& s, int& t, int& s_t_min_cut_cost)  
{  
    for (int i=0; i<9; i++) visit[i] = false; // initialize  
    for (int i=0; i<9; i++) w[i] = 0;  

    for (int i=0; i<V; ++i)  
    {  
        // 找出一個尚未加入A當中、且w(A, x)最大的x點。  
        int a = 0, max = -1e9;  
        for (int j=0; j<V; ++j)  
            if (!combine[i] && !visit[i] && w[i] > max)  
                max = w[i], a = i;  

        visit[a] = true;    // 加入a點到A集合  

        s = t; t = a;   // 不斷紀錄目前的Cut位置  
        s_t_min_cut_cost = w[t];    // 不斷紀錄目前的Cut權重  

        // 加入a點到A集合後,更新w(A, x)的值。  
        for (int b=0; b<V; ++b)  
            if (!combine[i] && !visit[b])  
                w[b] += map[a][b];  
    }  
}  

void stoer_wagner()  
{  
    for (int i=0; i<9; ++i) combine[i] = false;  

    int ans = 0;  
    for (int k=0; k<V-1; ++k)  
    {  
        // s點和t點在Cut不同側  
        int s, t, s_t_min_cut_cost;  
        maximum_adjacency_search(s, t, s_t_min_cut_cost);  
        if (s_t_min_cut_cost < ans) ans = s_t_min_cut_cost;  

        // s點和t點在Cut同側  
        combine[t] = true;      // 把t點標記為被合併過了,變成不存在。  
        for (int i=0; i<V; ++i) // 把t點合併至s點後,更新邊的權重值。  
            if (!combine[i])  
            {  
                map[i][s] += map[i][t];  
                map[s][i] += map[t][i];  
            }  
    }  
    cout << "Min-Cut的權重為" << ans << endl;  
}   

 

找出一個 Min-Cut ( adjacency matrix ):

纪录最小值是出现在哪里。【待补文字】

 

 

 

 

 

找出所有的 Min-Cut:

歡迎提供想法。【待補文字】

這裡提供兩題練習題。

Uva 10480 10989

 

 

 

 

Min-Cut: Karger's Algorithm:

用来求出一张图的其中一个 Min-Cut (或 Max-Cut )。特别的是,这是个随机演算法,属于 Monte Carlo Algorithm ,也就是不保证答案百分之百正确。

 

 

 

 

 

演算法:

 

任取图上两点,这两点要嘛就是在 Min-Cut 同侧,要嘛就是在 Min-Cut 不同侧。如果这两点在 Min-Cut 同侧,可以使用 contraction 来减少一个点,缩小问题范畴,不致影响 Min-Cut 的权重。

1. 重复下面这件事V-1次,直到图上剩下两个点,刚好可以作出一个Cut

 甲、随机取图上一条边:猜测这条边不在Min-Cut上、这条边的两个端点在Min-Cut同侧。

 乙、Contraction:合并这条边的两个端点。

 

这个演算法近似于「 Minimum Spanning Tree: Kruskal's Algorithm 」:每次都选择一条边,让这条边的两个端点相连在一起。唯一的差异是 Karger's Algorithm 是随机地选择一条边,而 Kruskal's Algorithm 是选择权重最小(或最大)的边。

 

 

 

 

正確率:

既然是随机演算法,就得计算一下正确率了!下面这段正确率的证明,是我从论文中读到的。我觉得这个证明非常吊诡,不知道我是否有理解错误:

 

假设一张图的 Min-Cut 至少有 c 条边。然后,令图上每一个点至少都连着 c 条边,才能使这张图的任一个 Cut 至少都有 c 条边、任一个 Cut 都可能成为 Min-Cut

 

根据此设定,可推导出这张图上至少共有 c*V/2 条边。 V 是点的总数。

 

基于方才的假设,随机从图上选择一条边,这条边在 Min-Cut 上的机率至多是 c / (c*V/2) = 2/V ,不在 Min-Cut 上的机率至少是 1-2/V

 

Karger's Algorithm 每个步骤所选到的边,都必须不是 Min-Cut 上的边,结果才会正确。每个步骤都会减少图上的一个点,推得 Karger's Algorithm 的正确率至少是 [1-2/V] * [1-2/(V-1)] * … * [1-2/4] * [1-2/3] = 1/C{V,2} = Ω(1/V^2) = Ω(V^-2)

 

根据这个正确率,只要进行 V^2 次以上的 Karger's Algorithm ,结果就会相当准确了!

 

 

 

 

 

Min-Cut: Karger-Stein Algorithm:

Karger-Stein Algorithm Karger's Algorithm 的加强版。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值