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

  • 相关阅读:
    三层浅析及演示样例分析
    WIN7 以下创建cocos2d-x3.0+lua项目
    hdu1814 Peaceful Commission,2-sat
    卸载mysql残留
    OA 权限控制
    开源 java CMS
    BestCoder Round #3 A,B
    K-近邻算法python实现
    04-08移动字母
    移动web开发前准备知识了解(html5、jquery)笔记
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4003908.html
Copyright © 2011-2022 走看看