• 全局最小割Stoer-Wagner算法


    借鉴:http://blog.kongfy.com/2015/02/kargermincut/

    提到无向图的最小割问题,首先想到的就是Ford-Fulkerson算法解s-t最小割,通过Edmonds–Karp实现可以在O(nm2)时间内解决这个问题(n为图中的顶点数,m为图中的边数)。

    但是全局最小割和s-t最小割不同,并没有给定的指定的源点s和汇点t,如果通过Ford-Fulkerson算法来解这一问题,则需要枚举汇点t(共n1),时间复杂度为O(n2m2)

    Can we do better?

    答案是肯定的,Karger在攻读博士学位期间(Orz…)提出了非常著名的基于随机化的全局最小割算法,算法非常简单,简单到不敢相信它是正确的,算法描述如下:

      1. 在图中随机取一条边,将边的两个端点合并(contraction),同时消除所有由于合并而形成自环的边
    Contraction

    Contraction

    1. 重复步骤1直到图中仅剩下两个点
    2. 将最终两点之间的边作为找的割返回

    合并的边权值相加

    1.min=MAXINT,固定一个顶点P

    2.从点P用“类似”prim的s算法扩展出“最大生成树”记录最后扩展的顶点和最后扩展的边

    3.计算最后扩展到的顶点的切割值(即与此顶点相连的所有边权和),若比min小更新min

    4.合并最后扩展的那条边的两个端点为一个顶点(当然他们的边也要合并,这个好理解吧?)

    5.转到2,合并N-1次后结束

    6.min即为所求,输出min

     prim本身复杂度是O(n^2),合并n-1次,算法复杂度即为O(n^3),如果在prim中加堆优化,复杂度会降为O((n^2)logn)0.

    #include <iostream>
    #include <cstdio>
    #include <sstream>
    #include <cstring>
    #include <map>
    #include <cctype>
    #include <set>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <cmath>
    #include <bitset>
    #define rap(i, a, n) for(int i=a; i<=n; i++)
    #define rep(i, a, n) for(int i=a; i<n; i++)
    #define lap(i, a, n) for(int i=n; i>=a; i--)
    #define lep(i, a, n) for(int i=n; i>a; i--)
    #define rd(a) scanf("%d", &a)
    #define rlld(a) scanf("%lld", &a)
    #define rc(a) scanf("%c", &a)
    #define rs(a) scanf("%s", a)
    #define rb(a) scanf("%lf", &a)
    #define rf(a) scanf("%f", &a)
    #define pd(a) printf("%d
    ", a)
    #define plld(a) printf("%lld
    ", a)
    #define pc(a) printf("%c
    ", a)
    #define ps(a) printf("%s
    ", a)
    #define MOD 2018
    #define LL long long
    #define ULL unsigned long long
    #define Pair pair<int, int>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define _  ios_base::sync_with_stdio(0),cin.tie(0)
    //freopen("1.txt", "r", stdin);
    using namespace std;
    const int maxn = 105, INF = 0x7fffffff;
    
    int n, m;
    int way[maxn][maxn], d[maxn], bin[maxn];
    bool vis[maxn];
    
    int contract(int &s, int &t)
    {
        mem(vis, false);
        mem(d, 0);
        int k, maxc, ans;
        rap(i, 1, n)
        {
            k = -1, maxc = -INF;
            rap(j, 1, n)
                if(!bin[j] && !vis[j] && d[j] > maxc)
                    k = j, maxc = d[j];
            if(k == -1) return ans;
            s = t, t = k, ans = maxc;
            vis[k] = true;
            rap(j, 1, n)
                if(!bin[j] && !vis[j])
                    d[j] += way[k][j];
        }
        return ans;
    }
    
    int SW()
    {
        int mincut = INF, ans, s, t;
        rep(i, 1, n)
        {
            ans = contract(s, t);
            bin[t] = 1;
            mincut = min(ans, mincut);
            if(mincut == 0) return 0;
            rap(j, 1, n)
                if(!bin[j])
                    way[s][j] = (way[j][s] += way[j][t]);
        }
        return mincut;
    }
    
    int main()
    {
        while(scanf("%d%d", &n, &m) != EOF)
        {
            mem(way, 0);
            mem(bin, 0);
            int u, v, w;
            rap(i, 1, m)
            {
                rd(u), rd(v), rd(w);
                u++, v++;
                way[u][v] += w;
                way[v][u] += w;
            }
            cout << SW() << endl;
        }
    
        return 0;
    }
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    redis你要知道的事
    Nginx七层负载均衡的几种调度算法
    JQuery的父、子、兄弟节点选择器
    laravel通用和万能路由
    jquery竖向企业组织结构图
    phpexcel功能操作
    animatext.js使用介绍
    Centos firewalld开放端口
    获取微信accesstoken并文件缓存方式
    css处理文字不换行、换行截断、溢出省略号
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/10008678.html
Copyright © 2020-2023  润新知