zoukankan      html  css  js  c++  java
  • POJ 2914 Minimum Cut【最小割 Stoer-Wangner】

    题意:求全局最小割

    不能用网络流求最小割,枚举举汇点要O(n),最短增广路最大流算法求最大流是O(n2m)复杂度,在复杂网络中O(m)=O(n2),算法总复杂度就是O(n5);就算你用其他求最大流的算法,算法总复杂度也要O(n4)所以用网络流算法求解最小割集复杂度不会低于O(n4)。所以就要用Stoer_Wagner算法。算法复杂度为O(n3)。如果加堆优化,复杂度会降为O(n2logn)

    Stoer_Wagner算法: 
    Stoer_Wagner算法是求无向图全局最小割的一个有效算法,最坏时间复杂度O(n3),主要思想是先找任意2点的最小割,然后记录下这个最小割,再合并这2个点。这样经过n1次寻找任意2点最小割,每次更新全局最小割。
    最后整张图缩成一个点,算法结束,所保存下来的最小割就是全局最小割。

    具体步骤

    如果G的最小割Cut把G分成M,N两个点集,那么枚举的s和t无非以下两种情况:

    ①:如果s∈M,t∈N则Min-C(s,t) = Cut(最终的最小割)

    ②:如果s,t∈M(或s,t∈N)则Min-C (s,t) >= Cut(合并s和t后并不影响最小割,所以就把st合并了得到中间结果图G',继续在图G'上求最小割直到命中条件①)

    因为利用到了中间结果G',G'<G,所以降低了复杂度。另外,这个合并的思想有点像Prim最小生成树算法,prim维护的dis数组的含义是集合A外的点到到集合树的最短边权,而StoerWagner维护的w数组是集合A外的点,到集合A所有点的边权之和【割集】。

    至于②中提到的合并操作,定义为Contract(s,t) := 删掉点 s, t 及边(s, t),加入新节点 c,对于任意 v ∈ 与s,t联通的点集,做一条新的边w(v, c) = w(c, v) = w(s, v) + w(t, v) 

    1. 设最小割cut=INF, 任选一个点s到集合A中, 定义W(A, p)为A中的所有点到A外一点p的权值总和.
    
    2. 对刚才选定的s, 更新W(A,p)(该值递增).
    
    3. 选出A外一点p, 且W(A,p)最大的作为新的s, 若A!=|V|, 则继续2. //最大割

    4
    . 把最后进入A的两点记为s和t, 用W(A,t)更新cut.

    5
    . 合并st,即新建顶点u, 边权w(u, v)=w(s, v)+w(t, v), 删除顶点s和t, 以及与它们相连的边

    6. 若|V|!=1则继续1.

    StoerWagner的正确性: 
    ST是图G2个顶点,图G的全局最小割要么是ST的最小割,此时STG的全局最小割的2不同的子集中,要么就是G中将ST合并得的的新图G的全局最小割,此时S和T在G的全局最小割的同一子集中。

    合并后对边权进行调整对全局最小割没有任何影响。所以只需要不断求出当前图中任意2个点的最小割,然后合并这2个点。不断缩小图的规模求得最小割。

           5,6合并成         

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 int e[510][510]; //边权
     8 int w[510];      //各点与A集合中所有点的边权之和, w(A,x)=∑w(id[i],x) id[i]∈A
     9 int id[510];     //顶点的重新索引,由于合并顶点的需要
    10 bool vis[510];   //顶点是否已访问
    11 
    12 int main()
    13 {
    14     int n,m;
    15     while(scanf("%d%d",&n,&m)!=EOF)
    16     {
    17         memset(e,0, sizeof(e));
    18         for(int i=0;i<n;i++)id[i]=i;//未合并之前,各顶点索引自己
    19         for(int i=0;i<m;i++)
    20         {
    21             int u,v,c;
    22             scanf("%d%d%d",&u,&v,&c);
    23             e[u][v]+=c;
    24             e[v][u]+=c;//无向图
    25         }
    26 
    27         int ans=0x3f3f3f3f;//全局最小割
    28         while(n>1)
    29         {
    30             memset(vis,0, sizeof(vis));
    31             memset(w,0, sizeof(w));
    32             int s,t=0;//最后两个顶点
    33             vis[0]=1;//默认第一个顶点入集合A
    34             for(int i=1;i<n;i++)
    35             {
    36                 s=t;
    37                 t=-1;
    38                 for(int j=1;j<n;j++)
    39                 {
    40                     if(!vis[j])
    41                     {
    42                         w[j]+=e[id[j]][id[s]];
    43                         if(t==-1||w[j]>w[t])t=j;//找最大的割集
    44                     }
    45                 }
    46                 vis[t]=1; //加入集合A
    47             }
    48             ans=min(ans,w[t]);
    49             for(int i=0;i<n;i++)  // 合并s,t为s点
    50             {
    51                 if(i==s||i==t)continue;
    52                 e[id[i]][id[s]]+=e[id[i]][id[t]];
    53                 e[id[s]][id[i]]+=e[id[i]][id[t]]; //边权w(s, v)=w(s, v)+w(t, v)
    54             }
    55             id[t]=id[--n]; // 赋值顶点n-1从而删除t点, 顶点数量-1
    56         }
    57         printf("%d
    ",ans);
    58     }
    59     return 0;
    60 }

     参考自:http://www.hankcs.com,yogykwan和QAQqwe

  • 相关阅读:
    IOC(控制反转)
    JQuery中的DOM操作
    【JQuery的选择器】
    JPA基本注解介绍
    JPA使用的HelloWorld
    JPA的介绍
    JQuery简介及HelloWorld
    SpringMvc处理post请求乱码的filter
    Sping3.0版本+Quartz完成定时任务
    CentOS下安装Subversion (SVN)
  • 原文地址:https://www.cnblogs.com/demian/p/9231088.html
Copyright © 2011-2022 走看看