无向图最小割 stoer_wagner算法

 1 const int  MAX_N = 1;
 2 int G[MAX_N][MAX_N];
 3 int v[MAX_N];            //    v[i]代表节点i合并到的顶点
 4 int w[MAX_N];            //    定义w(A,x) = ∑w(v[i],x),v[i]∈A
 5 bool visited[MAX_N];    //    用来标记是否该点加入了A集合
 6
 7 int stoer_wagner(int n)
 8 {
 9     int min_cut = inf;
10     for (int i = 0; i < n; ++i)
11     {
12         v[i] = i;        //    初始还未合并,都代表节点本身
13     }
14
15     while (n > 1)
16     {
17         int pre = 0;    //    pre用来表示之前加入A集合的点(在t之前一个加进去的点)
18         memset(visited, 0, sizeof(visited));
19         memset(w, 0, sizeof(w));
20         for (int i = 1; i < n; ++i)
21         {
22             int k = -1;
23             for (int j = 1; j < n; ++j)  //    选取V-A中的w(A,x)最大的点x加入集合
24             {
25                 if (!visited[v[j]])
26                 {
27                     w[v[j]] += G[v[pre]][v[j]];
28                     if (k == -1 || w[v[k]] < w[v[j]])
29                     {
30                         k = j;
31                     }
32                 }
33             }
34
35             visited[v[k]] = true;        //    标记该点x已经加入A集合
36             if (i == n - 1)                //    若|A|=|V|(所有点都加入了A),结束
37             {
38                 const int s = v[pre], t = v[k];        //    令倒数第二个加入A的点(v[pre])为s,最后一个加入A的点(v[k])为t
39                 min_cut = min(min_cut, w[t]);        //    则s-t最小割为w(A,t),用其更新min_cut
40                 for (int j = 0; j < n; ++j)            //    Contract(s, t)
41                 {
42                     G[s][v[j]] += G[v[j]][t];
43                     G[v[j]][s] += G[v[j]][t];
44                 }
45                 v[k] = v[--n];                        //    删除最后一个点(即删除t,也即将t合并到s)
46             }
47             // else 继续
48             pre = k;
49         }
50     }
51     return min_cut;
52 }
时间: 2024-12-22 08:49:30

无向图最小割 stoer_wagner算法的相关文章

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)最大的作为

求无向图最小割

先解释下名词的意思. 无向图的割:就是去掉一些边,使得原图不连通,最小割就是要去掉边的数量最小. 解决这个问题的常用办法就是Stoer-Wagner 算法: 先说下这个算法的步骤后面给出证明: 1.min=MAXINT,固定一个顶点P 2.从点P用类似prim的s算法扩展出"最大生成树",记录最后扩展的顶点和最后扩展的边 3.计算最后扩展到的顶点的切割值(即与此顶点相连的所有边权和),若比min小更新min 4.合并最后扩展的那条边的两个端点为一个顶点 5.转到2,合并N-1次后结束

Hdu 3691 Nubulsa Expo(无向图最小割)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3691 思路:无向图最小割模板题. 流量最小且汇点自定,则可在最小割T集中任选一点当做汇点. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define debu using namespace std; const int maxn=350; const in

最小割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-C(s,t): 设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(

利用Stoer-Wagner算法求无向图最小割

直接给出算法描述和过程实现: 算法步骤: 1. 设最小割cut=INF, 任选一个点s到集合A中, 定义W(A, p)为A中的所有点到A外一点p的权总和. 2. 对刚才选定的s, 更新W(A,p)(该值递增). 3. 选出A外一点p, 且W(A,p)最大的作为新的s, 若A!=G(V), 则继续2. 4. 把最后进入A的两点记为s和t, 用W(A,t)更新cut. 5. 新建顶点u, 边权w(u, v)=w(s, v)+w(t, v), 删除顶点s和t, 以及与它们相连的边. 6. 若|V|!=

BZOJ1001[BeiJing2006]狼抓兔子(无向图最小割)

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 这题的题意其实就是求一个最小割,但是由于是无向图,所以加边的时候,两边的流量都要是输入的权值,然后就是一个dinic求一下最小割. 但是这题貌似有很高超的技巧来搞,可以把平面图上的最小割转成对偶图上的最短路来做,这样可以起到很明显的优化效果.现在还不是很明白,如果以后明白了,会再来更新. dinic: #include <cstdio> #include <cstring&g

poj1966Cable TV Network——无向图最小割(最大流)

题目:http://poj.org/problem?id=1966 把一个点拆成入点和出点,之间连一条边权为1的边,跑最大流即最小割: 原始的边权赋成inf防割: 枚举源点和汇点,直接相邻的两个点不必枚举: 注意:1.源点为枚举点i的出点,汇点为枚举点j的入点: 2.读入方式,免空格: 3.在dinic跑最大流的过程中,会改变边权,因此每次枚举都要复制一组边跑最大流,以免影响后面: 另:数据中的点从0开始,所以读入的时候++来使用. 代码如下: #include<iostream> #incl

[HDOJ6081] 度度熊的王国战略(无向图最小割,数据水)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6081 无向图求割点,应该是个论文题,16年有一篇SW算法+斐波那契堆优化的论文. 但是这数据怎么这!么!水! 我在有生之年大概不会需要接触这篇论文了)flag 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 3030; 5 const int maxm = 100100; 6 const int inf

全局最小割Stoer-Wagner算法

1.min=MAXINT,固定一个顶点P 2.从点P用"类似"prim的s算法扩展出"最大生成树",记录最后扩展的顶点和最后扩展的边 3.计算最后扩展到的顶点的切割值(即与此顶点相连的所有边权和),若比min小更新min 4.合并最后扩展的那条边的两个端点为一个顶点(当然他们的边也要合并,这个好理解吧?) 5.转到2,合并N-1次后结束 6.min即为所求,输出min prim本身复杂度是O(n^2),合并n-1次,算法复杂度即为O(n^3),如果在prim中加堆优