• 网络流Dinic算法


    我的模板

    例题: https://vjudge.net/problem/HDU-4280

    struct Edge {
        int lst;
        int from;
        int to;
        int cap;
        int flow;
        Edge () { }
        Edge (int llst, int ffrom, int tto, int ccap, int fflow) : lst(llst), from(from), to(tto), cap(ccap), flow(fflow) { }
    };
    
    // Dinic 算法有3个重点:
    // 一个是 层次图
    // 一个是 阻塞流
    // 一个是 cur优化
    // 稠密点的可以再加上 炸点优化 
    
    class Dinic {
    public:
        Edge edge[maxn*2];
        int head[maxn];
        int cn, cm, cst, ced;
        int csz;
        bool vis[maxn];
        int dist[maxn]; // 节点到起点层次距离 
        int  cur[maxn];
        void init(int n, int m) {
            cn = n; cm = m;
            memset(head, 0, sizeof(head)); 
            csz = 2;  // 注意 这儿应该是偶数开始  因为 奇数^1等价于减1 偶数^1等价于加一. 
                      // 因为我前向星是以0为结尾的 所以我必须从2开始. 
        }
         
        void add(int u, int v, int c) {
             edge[csz] = Edge(head[u], u, v, c, 0);   
             head[u]   = csz++;
             edge[csz] = Edge(head[v], v, u, 0, 0);  // 反向边,记得容量为0, 但是有些情况是可以修改的. 例如在建无向图的时候. 
             head[v]   = csz++;
        }
        
        // bfs划 层次图 
        bool bfs() {
            memset(vis, 0, sizeof(vis));
            queue<int> q;
            q.push(cst);
            vis[cst] = true;
            dist[cst] = 0;
            int i, v, u;
            while (!q.empty()) {
                u = q.front(); q.pop();
                for (i=head[u]; i; i=edge[i].lst) {
                    v = edge[i].to;
                    if (!vis[v] && edge[i].cap > edge[i].flow) { 
                        dist[v] = dist[u] + 1;
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
            return vis[ced];  // 说明不能到达汇点 
        }
        
        // dfs收割阻塞流 
        int dfs(int u, int limit) {
            if (u==ced || limit==0) return limit;
            int i, v, flow = 0, f;
            for (i=cur[u]; i; i=cur[u]=edge[i].lst) {
                v = edge[i].to;
                if (dist[u]+1==dist[v] && (f = dfs(v, min(limit, edge[i].cap - edge[i].flow))) > 0 ) {  // 找增广路
                      edge[i].flow += f;
                    edge[i^1].flow -= f;
                    flow  += f;
                    limit -= f;
                    if (limit == 0) break;
                }
            }
            if (!flow) dist[u] = -1;  // 这个第二个优化:炸点优化,说明这个点没有贡献了,再经过他也没有任何意义了,所以距离定义为-1. 
            return flow;
        }
        
        // 不断分割层次图,每一次分割后就收割一次阻塞流,直到不能再分割层次图
        int maxflow(int st, int ed) {
            cst = st; ced = ed;
            int i, res = 0;
            while (bfs()) {
                //  这是一个优化, cur[u]表示上次u节点访问到的dfs位置. 这样就不用每一次都从head[u]开始. 
                //  可以避免很多重复计算,如果没有这个优化,那么退化成Edmonds_Karp算法了...  这是第一个优化 还有一个炸点优化. 
                for (i=1; i<=cn; ++i) cur[i] = head[i];  
                res += dfs(st, inf);
            }    
            return res;
        } 
    }Dic;

    紫书模板

    struct Edge {
        int from, to, cap, flow;
        Edge (int u, int v, int c, int f) : from(u), to(v), cap(c), flow(f) { }
    };
    struct Dinic {
        int n, m, s, t;
        vector<Edge> edges;
        vector<int> G[maxn];
        bool vis[maxn];
        int d[maxn];
        int cur[maxn];
        
        void init(int n) {
            this->n = n;
            for (int i=0; i<=n; ++i) G[i].clear();
    edges.clear(); } inline
    void add(int u, int v , int val) { edges.push_back(Edge(u, v, val, 0)); edges.push_back(Edge(v, u, 0, 0)); m = edges.size(); G[u].push_back(m-2); G[v].push_back(m-1); } bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(s); d[s] = 0; vis[s] = true; while (!Q.empty()) { int x = Q.front(); Q.pop(); for (int i=0, sz=G[x].size(); i<sz; ++i) { Edge &e = edges[G[x][i]]; if (!vis[e.to] && e.cap > e.flow) { vis[e.to] = true; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[t]; } int DFS(int x, int a) { if (x==t || a==0) return a; int flow = 0, f; for (int &i=cur[x], sz = G[x].size(); i<sz; ++i) { Edge &e = edges[G[x][i]]; if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0 ) { e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; a -= f; if (a == 0) break; } } return flow; } int maxflow(int s, int t) { this->s = s; this->t = t; int flow = 0; while (BFS()) { memset(cur, 0, sizeof(cur)); flow += DFS(s, inf); } return flow; } }Dic;
  • 相关阅读:
    深入浅出了解OCR识别票据原理(Applying OCR Technology for Receipt Recognition)
    OCR技术浅探:基于深度学习和语言模型的印刷文字OCR系统
    Python 3.6.4 / win10 使用pip安装keras时遇到依赖的PyYAML安装出错
    简单http代理服务器搭建
    Socket之心跳包实现思路
    设计模式之访问者模式
    设计模式之责任链模式
    设计模式之策略者模式
    C#将.spl剥离成.emf文件格式
    设计模式之状态者模式
  • 原文地址:https://www.cnblogs.com/cgjh/p/9497507.html
Copyright © 2020-2023  润新知