POJ 2914 - Minimum Cut - [stoer-wagner算法讲解/模板]
首先是当年stoer和wagner两位大佬发表的关于这个算法的论文:A Simple Min-Cut Algorithm
直接上算法部分:
分割线 begin
在这整篇论文中,我们假设一个普通无向图G=(V,E),其中每条边e都有一个正实数权值w(e)。
如果我们知道:怎样找到两个节点s,t,以及怎样得到对于s-t的最小割,我们就几乎解决了整个问题:
定理2.1:
设s和t是图G中的两个节点,设G/{s,t}是合并s和t后得到的图,
则图G的全局最小割可以通过“图G对于s-t的最小割”和“图G/{s,t}的全局最小割”得到。
定理说明:
若图G存在一个全局最小割,使得s和t被分割,那么,图G的s-t最小割就等于图G的全局最小割。
否则(即全局最小割没有分割s和t),图G的全局最小割就等于图G/{s,t}的全局最小割。
因此,我们可以使用一个寻找任意s-t最小割的程序来构建一个递归算法,从而寻找一个图的全局最小割。
下面的算法(使用一些骚操作搜索方法),可以产生我们想得到的s-t最小割。
MinimumCutPhase(G,w,a) //分阶段(phase),每个阶段都产生相应的当前阶段最小割
{
A←{a}
while( A ≠ V )
{
选取“最紧密相连的点”加入A
}
记录当前阶段的割,并且合并最后加入的两个点
}
呵,听起来就很玄乎,什么玩意儿呢,下面有解释。
A是作为V的一个子集,开始时是空集,我们任取一个点,加入到A中,然后通过某个规则不断地往A中加入点,直到A == V为止,那是什么规则呢?
在每一步的加点操作中,我们选择集合(V - A)中和A“最紧密相连的点”加入A,那什么是“最紧密相连的点”呢?
设:点y∈ V - A ,且点y为与集合A直接相连的点,所有点y的集合为Y;
所有与集合A直接相连的边的权重总和为w(A,y);
则:“最紧密相连的点” z 满足: z ∈ Y,并且w(A,z)为所有w(A,y)中最大的。
通俗的说,就是V - A集合里,找一个直接与A相连的点,这个点是 Σ(该点所有与A直接相连的边的权值) 最大的那个。
(不难看出,这是一种类似于prim算法生成类似最大生成树的算法)
在我们不断往A加点的过程中,记录下最后加入A的两个点,记为s和t,对这两个点进行合并操作(merge):
删除点s和点t,加入新的点u作为代替,所有原本从s或t点出发的边(edge< s , t >除外,这条边删除;并且设这些边到达的点为x),都用一条新的edge< u , x >代替;
并且 edge< u , x >.weight = edge< s , x >.weight + edge< t , x >.weight ; (若某条边不存在,则定义其weight=0)
(当然需要注意的是,所有讨论都是建立在无向图上,故这里的出发、到达不代表这条边的方向,只是单纯描述该边的两个端点)
然后,我们把当前分割s和t的割(cut),叫做阶段割(the-cut-of-phase),不难得到,阶段割等于w(A,t) (注意,此处的集合A表示加入点t前的集合A);
then,所有阶段割中最小的,即本算法的结果,即我们想求的全局最小割。
MinimumCut(G,w,a)
{
while(|V| > 1)
{
MinimumCutPhase(G,w,a)
if(阶段割 < 当前全局最小割) 当前全局最小割 = 阶段割
}
}
最后,注意到节点a在本算法整个过程中是一直不变的,实际上它也可以在每个阶段(phase)进行任意选择。
分割线 end
然后是论文中的example部分:
分割线 begin
这是第一次MinimumCutPhase(G,w,a)操作前和操作后的样子,
在此次MinimumCutPhase(G,w,a)操作中,进入集合A的点的顺序为: 2 → 3 → 4 → 7 → 8 → 6 → 5(s) → 1(t) ;
显然,此次的阶段割cut-of-the-phase.weight = w(A,t) = edge<1,2>.w + edge<1,5>.w = 5 ;
之后的操作与此类似,不再赘述,可以自行对照论文中的FIG。
分割线 end
当然,上stoer和wagner两位巨老当初的论文,装逼成分多余实际效用= =,感觉自己翻译也翻译的像一坨shit一样;
更多细节更深理解还请看中文:http://files.cnblogs.com/files/dilthey/stoer-wagner%E7%AE%97%E6%B3%95.pdf
先上算法模板以及解释:
#include<cstring>
#define MAXN 505
#define INF 0x3f3f3f3f
int n,m;//n个点,m条边
int edge[MAXN][MAXN],dist[MAXN];
bool vis[MAXN],bin[MAXN];
void init()
{
memset(edge,,sizeof(edge));
memset(bin,,sizeof(bin));
}
int merge(int &s,int &t)//对应论文中的MinimumCutPhase()
{
memset(dist,,sizeof(dist));
memset(vis,,sizeof(vis));
int k,mincut,maxc;
for(int i=;i<=n;i++)
{
k=-, maxc=-;
for(int j=;j<=n;j++) if(!bin[j] && !vis[j] && dist[j] > maxc) {k=j;maxc=dist[j];}
//寻找"the most tightly connected vertex"
if(k == -) return mincut;
vis[k]=true;//点k加入集合A
s=t; t=k;//不断移动s和t,保证他们是最后进入集合A的两个点
mincut=maxc;//不断更新mincut为w(A,t)
for(int j=;j<=n;j++) if(!bin[j] && !vis[j]) dist[j]+=edge[k][j];//计算所有的w(A,y)
}
return mincut;
}
int stoer_wagner()
{
int mincut=INF,s,t,ans;
for(int i=;i<=n-;i++)//merge(s,t)一次减少一个点,|V|要从n减少到1,故要进行n-1次
{
ans=merge(s,t);
bin[t]=;//把t合并到s中
if(ans<mincut) mincut=ans;
if(mincut==) return ;
for(int j=;j<=n;j++) if(!bin[j]) edge[s][j]=(edge[j][s]+=edge[j][t]);//更新所有从s出发的边
}
return mincut;
}
时间复杂度O(n³);
再说POJ2914,
题目链接:http://poj.org/problem?id=2914
有了模板之后,就是模板题;
当然,需要注意的是,这道题目里,n个点标号是0~n-1,用这个模板的话需要在输入的时候自己+1;
另外,这道题目的输入有重边,所以存边的时候,使用“+=”,而不是“=”;
#include<cstdio>
#include<cstring>
#define MAXN 505
#define MAXM MAXN*MAXN/2
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
int edge[MAXN][MAXN],dist[MAXN];
bool vis[MAXN],bin[MAXN];
void init()
{
memset(edge,,sizeof(edge));
memset(bin,,sizeof(bin));
}
int merge(int &s,int &t)
{
memset(dist,,sizeof(dist));
memset(vis,,sizeof(vis));
int k,mincut,maxc;
for(int i=;i<=n;i++)
{
k=-, maxc=-;
for(int j=;j<=n;j++) if(!bin[j] && !vis[j] && dist[j] > maxc) {k=j;maxc=dist[j];}
if(k == -) return mincut;
vis[k]=true;
s=t; t=k;
mincut=maxc;
for(int j=;j<=n;j++) if(!bin[j] && !vis[j]) dist[j]+=edge[k][j];
}
return mincut;
}
int stoer_wagner()
{
int mincut=INF,s,t,ans;
for(int i=;i<=n-;i++)
{
ans=merge(s,t);
bin[t]=;
if(ans<mincut) mincut=ans;
if(mincut==) return ;
for(int j=;j<=n;j++) if(!bin[j]) edge[s][j]=(edge[j][s]+=edge[j][t]);
}
return mincut;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
edge[a+][b+]+=c;
edge[b+][a+]+=c;
}
printf("%d\n",stoer_wagner());
}
}
POJ 2914 - Minimum Cut - [stoer-wagner算法讲解/模板]的更多相关文章
- POJ 2914 Minimum Cut Stoer Wagner 算法 无向图最小割
POJ 2914 题意:给定一个无向图 小于500节点,和边的权值,求最小的代价将图拆为两个联通分量. Stoer Wagner算法: (1)用类似prim算法的方法求"最大生成树" ...
- POJ 2914 Minimum Cut 最小割算法题解
最标准的最小割算法应用题目. 核心思想就是缩边:先缩小最大的边.然后缩小次大的边.依此缩小 基础算法:Prime最小生成树算法 只是本题測试的数据好像怪怪的,相同的算法时间执行会区别非常大,并且一样的 ...
- POJ 2914 Minimum Cut 最小割图论
Description Given an undirected graph, in which two vertices can be connected by multiple edges, wha ...
- POJ 2914 Minimum Cut【最小割 Stoer-Wangner】
题意:求全局最小割 不能用网络流求最小割,枚举举汇点要O(n),最短增广路最大流算法求最大流是O(n2m)复杂度,在复杂网络中O(m)=O(n2),算法总复杂度就是O(n5):就算你用其他求最大流的算 ...
- POJ 2914 Minimum Cut
Minimum Cut Time Limit: 10000MS Memory Limit: 65536K Total Submissions: 9319 Accepted: 3910 Case ...
- POJ 2914 Minimum Cut (全局最小割)
[题目链接] http://poj.org/problem?id=2914 [题目大意] 求出一个最小边割集,使得图不连通 [题解] 利用stoerwagner算法直接求出全局最小割,即答案. [代码 ...
- POJ 2914 Minimum Cut 全局最小割
裸的全局最小割了吧 有重边,用邻接矩阵的时候要小心 #include<iostream> #include<cstdio> #include<bitset> #in ...
- poj Minimum( CutStoer Wagner算法)
Minimum Cut 题目: 给出一张图.要求你删除最小割权和图. 算法分析: //////////////////// 转载 --- ylfdrib ///////////////// ...
- POJ2914 Minimum Cut —— 最小割
题目链接:http://poj.org/problem?id=2914 Minimum Cut Time Limit: 10000MS Memory Limit: 65536K Total Sub ...
随机推荐
- Java实现非法访问异常
创建ExceptionTest类,在该类的main()方法中,使用反射获得String类的所有域,不要使用setAccessible方法修改这些域的可见性,然后通过反射获得私有域中与”hash”相匹配 ...
- CentOS下安装vsftpd
因为FTP的端口是 两个,一个是固定21端口,还有一个任意端口的数据通道.关键是任意端口不好搞. 首先在vsftpd的配置文件中设置 任意端口的范围 [root@localhost root]# vi ...
- Ansible 管理任务计划
ansible 使用 cron 模块来管理任务计划: [root@localhost ~]$ ansible 192.168.119.134 -m cron -a "name='test c ...
- requests 安装
requests 是用来发送 HTTP 请求的一个库,requests 是对 urllib 和 urllib2 进行封装的一个模块,用来取代 urllib 和 urllib2,可以使用以下两种方法安装 ...
- 基于Elasticsearch 5.4.3的商品搜索系统
源码已提交至http://github.com
- Android textview及其子类
属性: android:autoLink设置是否当文本为URL链接/email/电话号码/map时,文本显示为可点击的链接.可选值(none/web/email/phone/map/all) andr ...
- EventHandler 与常见的.Net预定义委托
看着下面这两句事件定义及激发忽然有点不明白了, public event EventHandler<ExternalDataEventArgs> Submit; Submit(null, ...
- 【python3】爬取新浪的栏目分类
目标地址: http://www.sina.com.cn/ 查看源代码,分析: 1 整个分类 在 div main-nav 里边包含 2 分组情况:1,4一组 . 2,3一组 . 5 一组 .6一组 ...
- LeetCode 44 Wildcard Matching(字符串匹配问题)
题目链接:https://leetcode.com/problems/wildcard-matching/?tab=Description '?' Matches any single chara ...
- [原]sublime Text2
sublime Text2 升级到 2.0.2 build 2221 64位 的破破解 sublime Text2 download website 链接: http://pan.baidu.com/ ...