zoukankan      html  css  js  c++  java
  • SW算法求全局最小割(Stoer-Wagner算法)

    我找到的唯一能看懂的题解:【ZZ】最小割集Stoer-Wagner算法

    似乎是一个冷门算法,连oi-wiki上都没有,不过洛谷上竟然有它的模板题,并且2017百度之星的资格赛还考到了。于是来学习一下。

    一些定义

    无向图的(全局)最小割:一个边权和最小的边集,断掉后图不联通。

    算法

    我们自然可以直接钦定一个 (S),枚举 (T),求最小割,其中最小值即为答案。不过复杂度过于高,大概是 (O(n^3m)),当遇到稠密图的时候,就是 (O(n^5))。(尽管这个复杂度非常虚,靠信仰或许能通过题)如果我们用最小割树,复杂度不会变。因此我们需要一个更快捷的方法。

    流程

    (没写证明是因为不会证明)

    (w[p]) 表示点集外一点 (p) 到当前维护的点集中所有点的权值和(类似加权度数)。

    1. 找到当前图中 (w[p]) 最大的点 (p),将 (p) 加入到当前集合,并更新其它 (w[p])

    2. 若集合不为全集,则重复 1 操作。

    3. 设最后加入点集的两点为 (s, t)(..., (s), (t)),最后的 (w[t]) 即为 (s, t) 的最小割。用此最小割更新答案,并合并 (s, t).

    4. 若当前点数仍大于2,则清空集合,回到 1 操作。

    由此可知,SW 算法的复杂度是 (O(n^3))

    关键代码

    使用邻接矩阵更方便。

    int v[N][N], w[N], s, t;//邻接矩阵,加权度数,源汇
    bool del[N], vis[N];//是否因合并被删除,是否在点集里
    inline int search() {//将点逐个加入点集,得到s,t,s-t最小割
    	memset(w, 0, sizeof(w));
    	memset(vis, 0, sizeof(vis));//清空集合
    	s = 0, t = 0;
    	int res = inf;
    	while(1) {
    		int p = 0, mx = -inf;
    		for (register int i = 1; i <= n; ++i) if (!del[i] && !vis[i])
    			if (w[i] > mx)	mx = w[i], p = i;
    		vis[p] = true;
    		if (!p)	return res;//没有点集以外的点了
    		s = t, t = p;
    		res = w[p];
    		for (register int i = 1; i <= n; ++i) if (!del[i] && !vis[i])
    			w[i] += v[i][p];
    	}
    }
    inline void SW() {//更新答案,合并
    	int ans = inf;
    	for (register int i = 1; i < n; ++i) {
    		MIN(ans, search());
    		if (!ans)	break;
    		del[t] = true;
    		for (register int j = 1; j <= n; ++j) if (!del[j]) {
    			v[s][j] += v[t][j];
    			v[j][s] += v[j][t];//无向图合并
    		}
    	}
    	printf("%d
    ", ans);
    }
    

    感性理解

    博客里说和 prim 算法有关系,但是我并不精通 prim 算法,因此理解起来会很费劲。

    现在我要发挥shadowice精神了

    纯属口胡,无任何逻辑。

    (w[p])(p) 到点集的“加权度数”,可以衡量 (p) 与点集的“紧密度”。我们每次首先选择与点集“紧密度”更大的点加入点集,最后加入的 (s, t) 就是与图“紧密度”最小的点了,因此 (w[t]) 是将 (t) 这个最“边远”的点割离图的最小费用。

    如果 (s, t) 在最终的最小割中不在同一连通块,那么答案会被这一轮计算出来;如果 (s, t) 在同一连通块,那么合并 (s, t) 也对答案没有影响。

    相关题目

    P5632 【模板】Stoer-Wagner算法

    模板题

    hdu 3002 King of Destruction

    模板题

    hdu 6081 度度熊的王国战略

    n <= 3000。尽管给了 20 秒,这道题仍然是不可做题。不过可以拿贪心水过。

  • 相关阅读:
    Java多线程——<八>多线程其他概念
    Java多线程——<七>多线程的异常捕捉
    逆向破解之160个CrackMe —— 022
    逆向破解之160个CrackMe —— 021
    逆向破解之160个CrackMe —— 020
    逆向破解之160个CrackMe —— 019
    逆向破解之160个CrackMe —— 018
    逆向破解之160个CrackMe —— 017
    逆向破解之160个CrackMe —— 016
    逆向破解之160个CrackMe —— 015
  • 原文地址:https://www.cnblogs.com/JiaZP/p/13300187.html
Copyright © 2011-2022 走看看