zoukankan      html  css  js  c++  java
  • 最小割Stoer-Wagner算法

    最小割Stoer-Wagner算法

     

    割:在一个图G(V,E)中V是点集,E是边集。在E中去掉一个边集C使得G(V,E-C)不连通,C就是图G(V,E)的一个割;

    最小割:G(V,E)的所有割中,边权总和最小的割就是最小割。

     

    G的任意s-t最小割Min-Cst):

    s,t是途中的两个点且边(s,t)∈E(即s,t之间存在一条边)。如果G的最小割Cut把G分成M,N两个点集

    ①:如果s∈M,t∈N则Min-C(s,t)= Cut(不讨论)

    ②:如果s,t∈M(或者s,t∈N)则Min-C(s,t)<= Cut

     

    我们来定义一个Contract(a,b)操作,即把a,b两个点合并,表示为删除节点b,把b的节点信息添加到a上,如下图是做了Contract(5,6)

    最小割 <wbr>Stoer-Wagner <wbr>算法

    最小割 <wbr>Stoer-Wagner <wbr>算法

    对于所点v有w(v,5)+=w(v,6)

     

    s-t最小割的方法

    定义w(A,x) = ∑w(v[i],x),v[i]∈A

    定义Ax为在x前加入A的所有点的集合(不包括x)

    1.令集合A={a},a为V中任意点

    2.选取V-A中的w(A,x)最大的点x加入集合

    3.若|A|=|V|,结束,否则更新w(A,x),转到2

    令倒数第二个加入A的点为s,最后一个加入A的点为t,则s-t最小割为w(At,t)

     

    Poj (pku) 2914 Minimum Cut

    的第三个case为例,图为

    最小割 <wbr>Stoer-Wagner <wbr>算法

    G(V,E)

    我们设法维护这样的一个w[],初始化为0;

    我们把V-A中的点中w[i]最大的点找出来加入A集合;

    V-A直到为空

    w[]的情况如下

    w[i]

    0

    1

    2

    3

    4

    5

    6

    7

    初始值

    0

    0

    0

    0

    0

    0

    0

    0

    A=A∪{0}

    ---

    1

    1

    1

    1

    0

    0

    0

    A=A∪{1}

     

    ---

    2

    2

    1

    0

    0

    0

    A=A∪{2}

     

     

    ---

    3

    1

    0

    0

    0

    A=A∪{3}

     

     

     

    ---

    1

    0

    0

    1

    A=A∪{4}

     

     

     

     

    ---

    1

    1

    2

    A=A∪{7}

     

     

     

     

     

    2

    2

    ---

    A=A∪{5}

     

     

     

     

     

    ---

    3

     

    A=A∪{6}

     

     

     

     

     

     

    ---

     

     

    每次w[i]+=∑(i,a)的权值a∈A

    记录最后加入A的节点为t=6,倒数第二个加入A的为s=5,则s-t的最小割就为w[s],在图中体现出来的意思就是5-6的最小割为w[s]=3

    然后我们做Contract(s,t)操作,得到下图

    最小割 <wbr>Stoer-Wagner <wbr>算法

    G(V’,E’)

    重复上述操作

     

    w[i]

    0

    1

    2

    3

    4

    5

    7

    初始值

    0

    0

    0

    0

    0

    0

    0

    A=A∪{0}

    ---

    1

    1

    1

    1

    0

    0

    A=A∪{1}

     

    ---

    2

    2

    1

    0

    0

    A=A∪{2}

     

     

    ---

    3

    1

    0

    0

    A=A∪{3}

     

     

     

    ---

    1

    0

    1

    A=A∪{4}

     

     

     

     

    ---

    2

    2

    A=A∪{5}

     

     

     

     

     

    ---

    4

    A=A∪{7}

     

     

     

     

     

     

    ---

    s=5,t=7    s-t最小割是4

    Contract(s,t)得到

    最小割 <wbr>Stoer-Wagner <wbr>算法

     

     

    w[i]

    0

    1

    2

    3

    4

    5

    初始值

    0

    0

    0

    0

    0

    0

    A=A∪{0}

    ---

    1

    1

    1

    1

    0

    A=A∪{1}

     

    ---

    2

    2

    1

    0

    A=A∪{2}

     

     

    ---

    3

    1

    0

    A=A∪{3}

     

     

     

    ---

    1

    1

    A=A∪{4}

     

     

     

     

    ---

    4

    A=A∪{5}

     

     

     

     

     

    ---

    s=4,t=5    s-t最小割是4

    Contract(s,t)得到

    最小割 <wbr>Stoer-Wagner <wbr>算法


     

     

    w[i]

    0

    1

    2

    3

    4

    初始值

    0

    0

    0

    0

    0

    A=A∪{0}

    ---

    1

    1

    1

    1

    A=A∪{1}

     

    ---

    2

    2

    1

    A=A∪{2}

     

     

    ---

    3

    1

    A=A∪{3}

     

     

     

    ---

    2

    A=A∪{4}

     

     

     

     

    ---

    s=3,t=4    s-t最小割是2,(此时已经得出答案,以下省略)

     

     AC代码

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <climits>
     7 #include <vector>
     8 #include <queue>
     9 #include <cstdlib>
    10 #include <string>
    11 #include <set>
    12 #include <stack>
    13 #define LL long long
    14 #define pii pair<int,int>
    15 #define INF 0x3f3f3f3f
    16 using namespace std;
    17 const int maxn = 510;
    18 int e[maxn][maxn],n,m;
    19 bool comb[maxn];
    20 int Find(int &s,int &t){
    21     bool vis[maxn];
    22     int w[maxn];
    23     memset(vis,false,sizeof(vis));
    24     memset(w,0,sizeof(w));
    25     int tmp = INF;
    26     for(int i = 0; i < n; ++i){
    27         int theMax = -INF;
    28         for(int j = 0; j < n; j++)
    29             if(!vis[j] && !comb[j] && w[j] > theMax)
    30                 theMax = w[tmp = j];
    31         if(t == tmp) break;
    32         s = t;
    33         vis[t = tmp] = true;
    34         for(int j = 0; j < n; j++)
    35             if(!vis[j] && !comb[j])
    36                 w[j] += e[t][j];
    37     }
    38     return w[t];
    39 }
    40 int solve(){
    41     int ans = INF,s,t;
    42     memset(comb,0,sizeof(comb));
    43     for(int i = 1; i < n; i++){
    44         s = t = -1;
    45         ans = min(ans,Find(s,t));
    46         for(int j = 0; j < n; j++){
    47             e[s][j] += e[t][j];
    48             e[j][s] += e[j][t];
    49         }
    50         comb[t] = true;
    51     }
    52     return ans;
    53 }
    54 int main() {
    55     int u,v,w;
    56     while(~scanf("%d %d",&n,&m)){
    57         memset(e,0,sizeof(e));
    58         while(m--){
    59             scanf("%d %d %d",&u,&v,&w);
    60             e[u][v] += w;
    61             e[v][u] += w;
    62         }
    63         printf("%d
    ",solve());
    64     }
    65     return 0;
    66 }

    转载自http://blog.sina.com.cn/s/blog_700906660100v7vb.html

  • 相关阅读:
    129. Sum Root to Leaf Numbers
    113. Path Sum II
    114. Flatten Binary Tree to Linked List
    112. Path Sum
    100. Same Tree
    300. Longest Increasing Subsequence
    72. Edit Distance
    自定义js标签库
    JS 实现Table相同行的单元格自动合并示例代码
    mysql 高版本only_full_group_by 错误
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4003908.html
Copyright © 2011-2022 走看看