题目大意

给一个无向图,包含 N 个点和 M 条边,问最少删掉多少条边使得图分为不连通的两个部分,图中有重边

数据范围:2<=N<=500, 0<=M<=N*(N-1)/2

做法分析

典型的无向图全局最小割,使用 Stoer-Wagner 算法

Stoer-Wagner 算法共执行 n-1 次 BFS,每次 BFS 得到一个当前图的最小 S-T 割,并且将最后 BFS 的两个点缩点,n-1 次 BFS 得到 n-1 个最小 S-T 割中的最小者就是整个无向图的全局最小割,为了讲述每次 BFS 执行的操作,先进行如下定义:

  令 g[i][j] 表示边 (i, j) 的权值,对于无向图,我们有 g[i][j]=g[j][i]

  令 w[u] 表示 u 和已经被 BFS 过的点的关联度,即 w[u]=∑g[v][u] 其中,v 是已经被 BFS 过的点,u 是未被 BFS 的点。初始时,所有点的 w 值全部为 0

  令 vs[u] 表示 u 是否已经被 BFS 过,vs[u]=1 表示 u 已经被 BFS 过。初始时,所有点的 vs 值全部为 0

每次 BFS 按如下步骤执行:

  1. 选出未被 BFS 过的点中,关联度(w 值)最大的点(如果有多个,任选一个),设为 u。如果所有的点都已经被 BFS 过,则退出当前 BFS 过程

  2. 用 u 更新所有未被 BFS 的点的关联度,即: w[v]+=g[u][v],其中 v 没有被 BFS 过

  3. 将 u 设置为 BFS 过,即将 vs[u] 的值由 0 变为 1

  设倒数第 2 个被 BFS 的点为 S,倒数第 1 个被 BFS 的点为 T,那么,w[T] 就是本次 BFS 得到的最小 S-T 割

每次 BFS 后,将最后 BFS 的两个点 S 和 T 缩成一个点 u,即:g[i][u]=g[i][S]+g[i][T]

每次 BFS 后,用得到的最小 S-T 割更新全局的最小割

n-1 次 BFS 后,全局最小割求出来了,图也被缩成了一个点

下面是一个例子

假设在进行 BFS 时有一个无向图如下:

图中,括号中的数字表示每个点的 w 值,初始化为 0,边上的值表示边权。现在选择一个具有最大关联度(w 值最大)的点,有多种选择时随意选取一个点,假设选取的是第 2 个点,将它标记为已经访问过的点,并更新其他未被访问过的点的关联度:

现在,第 3 个点的关联度最大,选它作为下一个 BFS 的点,将它标记为已经访问过的点,并用它更新其他未被访问过的点的关联度:

第 4 个点的关联度最大,选其作为下一个 BFS 的点,将它标记为已经访问过的点,并更新其他未被访问过的点的关联度:

第 7 个点的关联度最大,选其作为下一个 BFS 的点,将它标记为已经访问过的点,并更新其他未被访问过的点的关联度:

第 8 个点的关联度最大,选其作为下一个 BFS 的点,将它标记为已经访问过的点,并更新其他未被访问过的点的关联度:

第 6 个点的关联度最大,选其作为下一个 BFS 的点,将它标记为已经访问过的点,并更新其他未被访问过的点的关联度:

第 5 个点的关联度最大,选其作为下一个 BFS 的点,将它标记为已经访问过的点,并更新其他未被访问过的点的关联度:

第 1 个点的关联度最大,选其作为下一个 BFS 的点,将它标记为已经访问过的点,并更新其他未被访问过的点的关联度:

至此,所有的点都被 BFS 了一遍,最后访问的点是 1,倒数第二访问的点是 5:

那么,我们这次 BFS 的 S 点是 5,T 点是 1,这次 BFS 得到的最小 S-T 割为 w[T]=5(上图中绿色的点)

将 S 点和 T 点合并:

得到新图:

将所有的标记(包括关联度,是否访问过)清空,进行下一次 BFS ,直至所有的点缩成一个点为止:

这样,经过 n-1 次 BFS 之后,整个无向图的全局最小割就求出来了

时间复杂度不难分析:o(n^3)

但是,我想,如果在每次 BFS 的时候,就像 Dijkstra 一样用堆优化,应该可以把复杂度降低到 o(n^2log2(n))

详细证明,请看 A Simple Min-Cut Algorithm

参考代码

 #include <iostream>
#include <cstdio>
#include <cstring> using namespace std; struct Stoer_Wagner {
static const int N=, INF=(<<);
int G[N][N], W[N], Merge[N], S, T, minCut, n;
bool vs[N]; void init(int _n) {
n=_n;
memset(G, , sizeof G);
} void BFS() {
memset(vs, , sizeof vs);
memset(W, , sizeof W);
S=T=-;
int Max, id;
for(int cnt=; cnt<n; cnt++) {
Max=-INF;
for(int i=; i<n; i++)
if(!Merge[i] && !vs[i] && W[i]>Max)
Max=W[i], id=i;
if(id==T) return;
S=T, T=id;
minCut=Max;
vs[id]=;
for(int i=; i<n; i++) {
if(Merge[i] || vs[i]) continue;
W[i]+=G[id][i];
}
}
} int StoerWagner() {
memset(Merge, , sizeof Merge);
int ans=INF;
for(int cnt=; cnt<n; cnt++) {
BFS();
if(minCut<ans) ans=minCut;
if(ans==) return ans;
Merge[T]=;
for(int i=; i<n; i++) {
if(Merge[i]) continue;
G[S][i]+=G[T][i];
G[i][S]+=G[i][T];
}
}
return ans;
}
}; Stoer_Wagner fuck;
int n, m; int main() {
while(scanf("%d%d", &n, &m)!=EOF) {
fuck.init(n);
for(int i=, a, b, c; i<m; i++) {
scanf("%d%d%d", &a, &b, &c);
fuck.G[a][b]+=c;
fuck.G[b][a]+=c;
}
printf("%d\n", fuck.StoerWagner());
}
return ;
}

ZOJ 2753

题目链接 & AC 通道

ZOJ 2753 Min Cut (Destroy Trade Net)

ZOJ 2753 Min Cut (Destroy Trade Net)(无向图全局最小割)的更多相关文章

  1. poj2914 Minimum Cut 全局最小割模板题

    Minimum Cut Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 8324   Accepted: 3488 Case ...

  2. poj2914无向图的最小割

    http://blog.csdn.net/vsooda/article/details/7397449 //算法理论 http://www.cnblogs.com/ylfdrib/archive/20 ...

  3. POJ 2914 Minimum Cut (全局最小割)

    [题目链接] http://poj.org/problem?id=2914 [题目大意] 求出一个最小边割集,使得图不连通 [题解] 利用stoerwagner算法直接求出全局最小割,即答案. [代码 ...

  4. POJ 2914 Minimum Cut 全局最小割

    裸的全局最小割了吧 有重边,用邻接矩阵的时候要小心 #include<iostream> #include<cstdio> #include<bitset> #in ...

  5. poj2914无向图的最小割模板

    题意:给出无向图的点,边,权值.求最小割. 思路:根据题目规模,最大流算法会超时. 网上参考的模板代码. 代码: /*最小割集◎Stoer-Wagner算法:一个无向连通网络,去掉一个边集可以使其变成 ...

  6. zoj 2676 二分+ISAP模板求实型参数的最小割(0-1分数规划问题)(可做ISAP模板)

    /* 参考博文:http://www.cnblogs.com/ylfdrib/archive/2010/09/01/1814478.html 以下题解为转载代码自己写的: zoj2676 胡伯涛论文& ...

  7. [全局最小割][Stoer-Wagner 算法] 无向图最小割

    带有图片例子的 [BLOG] 复杂度是$(n ^ 3)$ HDU3691 // #pragma GCC optimize(2) // #pragma GCC optimize(3) // #pragm ...

  8. POJ 2914:Minimum Cut(全局最小割Stoer-Wagner算法)

    http://poj.org/problem?id=2914 题意:给出n个点m条边,可能有重边,问全局的最小割是多少. 思路:一开始以为用最大流算法跑一下,然后就超时了.后来学习了一下这个算法,是个 ...

  9. POJ 2914 Minimum Cut【最小割 Stoer-Wangner】

    题意:求全局最小割 不能用网络流求最小割,枚举举汇点要O(n),最短增广路最大流算法求最大流是O(n2m)复杂度,在复杂网络中O(m)=O(n2),算法总复杂度就是O(n5):就算你用其他求最大流的算 ...

随机推荐

  1. 为什么要设置getter和setter?

    面向对象语言中,通常把属性设置为私有,然后添加getter和setter方法来访问.有人说,这本质上和设置属性为公有没有区别,干脆把属性public算了.也有人反驳,这样做破坏了封装.但是,破坏了封装 ...

  2. 从配置sublimeClang插件中学到的

    1.不害怕失败的关键在于要事先为失败准备补救措施.2.人们害怕内部结构复杂的东西出错,并以自己缺乏对内部结构的认识为理由而放弃查错.其实某些情况下根本无需对内部结构有多么深入的认识,只需从外部观察就够 ...

  3. 使用ThreadSanitizer线程检查工具

    ThreadSanitizer又叫TSan,是一个检查线程Data Race的C/C++工具.它集成在新版的gcc和clang中,通过编译时加-fsanitize=thread,可以在运行时检测出Da ...

  4. attilax.java 注解的本质and 使用最佳实践(3)O7

    attilax.java 注解的本质and 使用最佳实践(3)O7 1. 定义pojo 1 2. 建立注解By eclipse tps 1 3. 注解参数的可支持数据类型: 2 4. 注解处理器 2 ...

  5. 喜大普奔!Fanvas正式对外开源了,一键把Flash转为Canvas动画!移动终端动画开发不再困难。

    http://code.tencent.com/ https://github.com/TencentOpen/Fanvas DEMO: http://kenkozheng.github.io/fan ...

  6. python BeautifulSoup实例测验

  7. Android系统分区理解及分区目录细解

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  8. Swift入门篇-字符串和字符

    今天主要是介绍一下字符串的用法 ,字符串的语法和object-c语法不太一样,但是思想是一样,就是写法不太一样.如果您对.net和java语法比较熟悉的话,那您几乎没有深压力.如果您对swift 基本 ...

  9. iOS:Tools:快速注释Doxygen

    Xcode5有个新特性就是自己定义的函数也会被检测集成到代码提示里面,也就是在Quick Help有提示.如 /** * @brief 设置id * * @param id 要设置的id */ +(v ...

  10. [C] zlstdint(让VC、TC等编译器自动兼容C99的整数类型)V1.0。支持Turbo C++ 3等DOS下的编译器

    作者:zyl910 以前我曾为了让VC++等编译器支持C99的整数类型,便编写了c99int库来智能处理(http://www.cnblogs.com/zyl910/p/c99int_v102.htm ...