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)最大的作为新的s, 若A!=G(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.

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6
 7 #define MAX_N 500 + 16
 8 #define INF 0x3f3f3f3f
 9
10 int G[MAX_N][MAX_N];
11 int v[MAX_N];            //    v[i]代表节点i合并到的顶点
12 int w[MAX_N];            //    定义w(A,x) = ∑w(v[i],x),v[i]∈A
13 bool visited[MAX_N];    //    用来标记是否该点加入了A集合
14
15 int stoer_wagner(int n)
16 {
17     int min_cut = INF;
18     for (int i = 0; i < n; ++i)
19     {
20         v[i] = i;        //    初始还未合并,都代表节点本身
21     }
22
23     while (n > 1)
24     {
25         int pre = 0;    //    pre用来表示之前加入A集合的点(在t之前一个加进去的点)
26         memset(visited, 0, sizeof(visited));
27         memset(w, 0, sizeof(w));
28         for (int i = 1; i < n; ++i)
29         {
30             int k = -1;
31             for (int j = 1; j < n; ++j)  //    选取V-A中的w(A,x)最大的点x加入集合
32             {
33                 if (!visited[v[j]])
34                 {
35                     w[v[j]] += G[v[pre]][v[j]];
36                     if (k == -1 || w[v[k]] < w[v[j]])
37                     {
38                         k = j;
39                     }
40                 }
41             }
42
43             visited[v[k]] = true;        //    标记该点x已经加入A集合
44             if (i == n - 1)                //    若|A|=|V|(所有点都加入了A),结束
45             {
46                 const int s = v[pre], t = v[k];        //    令倒数第二个加入A的点(v[pre])为s,最后一个加入A的点(v[k])为t
47                 min_cut = min(min_cut, w[t]);        //    则s-t最小割为w(A,t),用其更新min_cut
48                 for (int j = 0; j < n; ++j)            //    Contract(s, t)
49                 {
50                     G[s][v[j]] += G[v[j]][t];
51                     G[v[j]][s] += G[v[j]][t];
52                 }
53                 v[k] = v[--n];                        //    删除最后一个点(即删除t,也即将t合并到s)
54             }
55             // else 继续
56             pre = k;
57         }
58     }
59     return min_cut;
60 }
61
62 int main(int argc, char *argv[])
63 {
64     int n, m;
65     while (scanf("%d%d", &n, &m) != EOF)
66     {
67         memset(G, 0, sizeof(G));
68         while (m--)
69         {
70             int u, v, w;
71             scanf("%d%d%d", &u, &v, &w);
72             G[u][v] += w;
73             G[v][u] += w;
74         }
75         printf("%d\n", stoer_wagner(n));
76     }
77     return 0;
78 }
时间: 2024-10-01 14:32:29

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

求无向图最小割

先解释下名词的意思. 无向图的割:就是去掉一些边,使得原图不连通,最小割就是要去掉边的数量最小. 解决这个问题的常用办法就是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算法基本思想:如果能求出图中某两个顶点之间的最小割,更新答案后合并这两个顶点继续求最小割,到最后就得到答案. 算法步骤: ------------------------------------------------------------------------------------------------------------------------- (1)首先初始化,设最小割ans = INF                                

无向图最小割 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; +

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

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

利用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|!=

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

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

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的最

[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