zoukankan      html  css  js  c++  java
  • 全局最小割(模板)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define MAX_N 500 + 16
    #define INF 0x3f3f3f3f
    int G[MAX_N][MAX_N];
    int v[MAX_N];    // v[i]代表节点i合并到的顶点
    int w[MAX_N];    // 定义w(A,x) = ∑w(v[i],x),v[i]∈A
    bool visited[MAX_N];    // 用来标记是否该点加入了A集合
    int stoer_wagner(int n)
    {
        int min_cut = INF;
        for (int i = 0; i < n; ++i){
            v[i] = i;    // 初始还未合并,都代表节点本身
        }
        while (n > 1)
        {
            int pre = 0;    // pre用来表示之前加入A集合的点(在t之前一个加进去的点)
            memset(visited, 0, sizeof(visited));
            memset(w, 0, sizeof(w));
            for (int i = 1; i < n; ++i){
                int k = -1;
                for (int j = 1; j < n; ++j)  // 选取V-A中的w(A,x)最大的点x加入集合
                {
                    if (!visited[v[j]])
                    {
                        w[v[j]] += G[v[pre]][v[j]];
                        if (k == -1 || w[v[k]] < w[v[j]]){
                            k = j;
                        }
                    }
                }
                visited[v[k]] = true;    // 标记该点x已经加入A集合
                if (i == n - 1)    // 若|A|=|V|(所有点都加入了A),结束
                {
                    const int s = v[pre], t = v[k];    // 令倒数第二个加入A的点(v[pre])为s,最后一个加入A的点(v[k])为t
                    min_cut = min(min_cut, w[t]);    // 则s-t最小割为w(A,t),用其更新min_cut
                    for (int j = 0; j < n; ++j)    // Contract(s, t)
                    {
                        G[s][v[j]] += G[v[j]][t];
                        G[v[j]][s] += G[v[j]][t];
                    }
                    v[k] = v[--n];    // 删除最后一个点(即删除t,也即将t合并到s)
                }
    // else 继续
                pre = k;
            }
        }
        return min_cut;
    }
    int main(int argc, char *argv[]){
        int n, m;
        while (scanf("%d%d", &n, &m) != EOF){
            memset(G, 0, sizeof(G));
            while (m--){
                int u, v, w;
                scanf("%d%d%d", &u, &v, &w);
                G[u][v] += w;
                G[v][u] += w;
            }
            printf("%d
    ", stoer_wagner(n));
        }
        return 0;
    }
  • 相关阅读:
    VSCode:无法创建临时目录
    网页很卡的原因
    用css做三角形
    移动端加载页面出现抖动、未加载完成时布局杂乱问题解决
    vue中使用axios进行ajax请求数据(跨域配置)
    fetch和XMLHttpRequest
    1-5-JS基础-数组应用及实例应用
    图片左右切换
    轮播图片切换
    轮播图片切换(函数合并)
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/4822998.html
Copyright © 2011-2022 走看看