最小割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)

对于所点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为例,图为

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)操作,得到下图

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)得到


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)得到


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\n",solve());
64     }
65     return 0;
66 }

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

时间: 2024-10-16 03:41:00

最小割Stoer-Wagner算法的相关文章

图的全局最小割的Stoer-Wagner算法及例题

Stoer-Wagner算法基本思想:如果能求出图中某两个顶点之间的最小割,更新答案后合并这两个顶点继续求最小割,到最后就得到答案. 算法步骤: ------------------------------------------------------------------------------------------------------------------------- (1)首先初始化,设最小割ans = INF                                

POJ 2914 - Minimum Cut - 全局最小割,Stoer-Wagner算法

题目大意:给定一个N个点.M条边的无向带权图,边的权值均为正整数.若要使它变成非连通图,需要移除的边总权值最小是多少? N≤500,图中不存在自环,但可能有重边(这里题意没交代清楚). Stoer-Wagner算法裸题.英文维基:https://en.wikipedia.org/wiki/Stoer%E2%80%93Wagner_algorithm 该算法的思想之一是:对于一个无向连通图,选定某两点s,t,以及该图的一个s-t割C,则"C是该图的全局最小割"是"C是s-t的最

最大流, 最小割问题及算法实现

最大流(MaxFlow)问题 给定指定的一个有向图,其中有两个特殊的点源S(Sources)和汇T(Sinks),每条边有指定的容量(Capacity),求满足条件的从S到T的最大流(MaxFlow). 想象一条多条不同水流量的水管组成的网络, s为供水广, t为水用户, 最大流问题就是找到能够在s到t流通的最大水流量 一个流是最大流当且仅当其残存网络不包含任何增广路径(里面的名称在后面有详细解释) 流(Flow)的基本性质 设$C_{uv}$代表边u到v最大允许流量(Capacity), $f

最小割-poj-2914

poj-2914-Minimum Cut Description Given an undirected graph, in which two vertices can be connected by multiple edges, what is the size of the minimum cut of the graph? i.e. how many edges must be removed at least to disconnect the graph into two subg

hiho一下 第119周 #1398 : 网络流五&#183;最大权闭合子图 【最小割-最大流--Ford-Fulkerson 与 Dinic 算法】

#1398 : 网络流五·最大权闭合子图 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 周末,小Hi和小Ho所在的班级决定举行一些班级建设活动. 根据周内的调查结果,小Hi和小Ho一共列出了N项不同的活动(编号1..N),第i项活动能够产生a[i]的活跃值. 班级一共有M名学生(编号1..M),邀请编号为i的同学来参加班级建设活动需要消耗b[i]的活跃值. 每项活动都需要某些学生在场才能够进行,若其中有任意一个学生没有被邀请,这项活动就没有办法进行. 班级建设的活

【BZOJ2229】【ZJOI2011】最小割 {没有错,这道题的算法跟题帽是一样的!!!}

题解:分治求最小割. [l--r]里任意找两个作为s.t(不妨把s设为l位置上的点,t设为r位置上的点)求最小割,两层for循环枚举修改map[i][j]即两点间最小割值. 然后一部分属于S集,一部分属于T集,分治[l,L],[R,r],每次求完最小割值都全局进行修改. 最后每次询问暴力做就好了,无需任何优化即可AC. 代码: #include <queue> #include <cstdio> #include <cstring> #include <iostr

POJ 2914 Minimum Cut 最小割算法题解

最标准的最小割算法应用题目. 核心思想就是缩边:先缩小最大的边,然后缩小次大的边,依此缩小 基础算法:Prime最小生成树算法 不过本题测试的数据好像怪怪的,同样的算法时间运行会差别很大,而且一样的代码替换,居然会WA.系统出错的几率很小,难倒测试系统本题会有错误? 懒得继续测试这道题的系统了,反正算法正确,AC. #include <stdio.h> #include <string.h> #include <limits.h> const int MAX_N = 5

POJ2914 (未解决)无向图最小割|Stoer-Wagner算法|模板

还不是很懂,贴两篇学习的博客: http://www.hankcs.com/program/algorithm/poj-2914-minimum-cut.html http://blog.sina.com.cn/s/blog_700906660100v7vb.html 算法步骤: 1. 设最小割cut=INF, 任选一个点s到集合A中, 定义W(A, p)为A中的所有点到A外一点p的权总和. 2. 对刚才选定的s, 更新W(A,p)(该值递增). 3. 选出A外一点p, 且W(A,p)最大的作为

PCL—点云分割(最小割算法)

1.点云分割的精度 在之前的两个章节里介绍了基于采样一致的点云分割和基于临近搜索的点云分割算法.基于采样一致的点云分割算法显然是意识流的,它只能割出大概的点云(可能是杯子的一部分,但杯把儿肯定没分割出来).基于欧式算法的点云分割面对有牵连的点云就无力了(比如风筝和人,在不用三维形态学去掉中间的线之前,是无法分割风筝和人的).基于法线等信息的区域生长算法则对平面更有效,没法靠它来分割桌上的碗和杯子.也就是说,上述算法更关注能不能分割,除此之外,我们还需要一个方法来解决分割的"好不好"这个