pku2914(求最小割)

来源:互联网 发布:centos 7配置lamp环境 编辑:程序博客网 时间:2024/05/19 02:40

http://162.105.81.212/JudgeOnline/problem?id=2914

 

题意求一无向图的最小割,无源汇点. 500个点, 500 * 499 / 2条边 10s时间.

一个很傻很暴力的做法就是枚举源汇点求最小割,但是复杂度不是一般滴高.

下面是抄袭别人的Stoer-Wagner算法:

核心思想是迭代缩小规模算法基于这样一个事实:

 

对于图中任意两点st, 它们要么属于最小割的两个不同集中要么属于同一个集.

 

如果是后者那么合并st后并不影响最小割基于这么个思想如果每次能求出图中某两点之间的最小割然后更新答案后合并它们再继续求最小割就得到最终答案了算法步骤如下:

 

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的两点记为st, W(A,t)更新cut.

5. 新建顶点u, 边权w(u, v)=w(s, v)+w(t, v), 删除顶点st, 以及与它们相连的边.

6. |V|!=1则继续1.

 

看起来很简单每次像做最大生成树一样选最大""(注意这里其实不是边而是已经累计的权值之和就当是加权的度好了), 然后把最后进入的两个点缩到一块就可以了合并点最多有n-1而不加堆优化的primO(n^2)所以最终复杂度O(n^3), 要是你有心情敲一大坨代码还可以在稀疏图上用Fibonacci Heap优化一下不过网上转了一圈大多都是说能用Fibonacci Heap优化到怎样怎样的复杂度真正能自己写出来的恐怕也没几个看看uoregon(俄勒冈大学)的一大坨代码就有点寒. (http://resnet.uoregon.edu/~gurney_j/jmpc/fib.html)

 

特别注意几个地方网上的好几个Stoer-Wagner版本都存在一些小错误:

 

1. 算法在做"最大生成树"时更新的不是普通意义上的最大边而是与之相连的边的权值和当所有边都是单位权值时就是累计度.

2. "最后进入A的两点记为st", 网上对s有两种解释一是在t之前一个加进去的点二是t的前趋节点也就是最后选择的那条边的另一端正解是第一种!

3. 对于稠密图比如这题我用堆映射二分堆或者STL的优先队列都会TLE, 还不如老老实实O(n^3).

4. 这题数据中可能存在重边.

5. 注意判断n=0n=1的情况用并查集判下连通性.

 

 

原创粉丝点击