HDU 3002 King of Destruction(全局(无向图)最小割(SW))

来源:互联网 发布:接触网中级工软件 编辑:程序博客网 时间:2024/05/29 09:15

题目地址
题意:给你一个无向图,求出全局最小割。
思路:对于无向图,割的定义与网络流差不多,只不过没有了源点与汇点的说法而已。一个无向连通图。如果去掉一个边集可以使得该连通图变的不再连通那么这个边集就是一个割,当这些边的集合的边权最小的时候这个边集就叫做最小割。也就是说将一个连通图分成两个集合,当一个边的两个顶点分别属于这两个集合。那么这条边就属于这个割集。无向连通图的解决一般使用Stoer_Wagner算法。下图是SW的过程。
这里写图片描述
寻找 s, t 两点,然后合并于 s 点。
以上图像来自论文。
推荐一篇博客讲解SW算法。

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 110#define M 300010 #define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1000000007;int n, m;int mapp[N][N];bool vis[N];//是否已并入集合bool in[N];//该点是否已经合并到其它点 int len[N];//记录每个点的连通度 struct Stoer_wagner {    int s, t;//    void init() {        memset(mapp, 0, sizeof(mapp));    }    int solve(){//找最大生成树        memset(vis, false, sizeof(vis));        memset(len, 0, sizeof(len));        int minlen;//找到的s-t割          int to;        for (int i = 1; i <= n; i++) {            int mmax = -inf;            for (int j = 1; j <= n; j++) {                if (!in[j] && !vis[j] && mmax < len[j]) {//找最大的len值                     to = j;                    mmax = len[j];                }            }            if (to == t) {//找不到点 图本身不连通                  break;            }            vis[to] = true;//标记 已经并入集合              minlen = mmax;            s = t;            t = to;// 记录前、后点              for (int j = 1; j <= n; j++) {//继续找不在集合 且 没有被合并过的点                  if (in[j] || vis[j]) {                    continue;                }                len[j] += mapp[to][j];//累加 连通度              }        }        return  minlen;    }    int stoer_wagner() {        memset(in, false, sizeof(in));        int ans = inf;        for (int i = 1; i < n; i++) {            ans = min(ans, solve());            if (ans == 0) return 0;//本身不连通            in[t] = true;            for (int j = 1; j <= n; j++) {//把t点合并到s点                  if (in[j]) continue;//已经合并                  mapp[s][j] += mapp[t][j];                mapp[j][s] += mapp[j][t];            }        }        return ans;    }}sw;int main() {    cin.sync_with_stdio(false);    int a, b, c;    while (cin >> n >> m) {        sw.init();        for (int i = 0; i < m; i++) {            cin >> a >> b >> c;            a++;            b++;            mapp[a][b] += c;            mapp[b][a] += c;        }        cout << sw.stoer_wagner() << endl;    }    return 0;}
阅读全文
0 0
原创粉丝点击