zoukankan      html  css  js  c++  java
  • POJ 1273 Drainage Ditches(网络流dinic算法模板)

    POJ 1273
    给出M条边,N个点,求源点1到汇点N的最大流量。

    本文主要就是附上dinic的模板,供以后参考。

    #include <iostream>
    #include <stdio.h>
    #include <algorithm>
    #include <queue>
    #include <string.h>
    
    /*
    POJ 1273
    dinic算法模板
    
    边是有向的,而且存在重边,且这里重边不是取MAX,而是累加和
    */
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int maxn=201;
    int pri[maxn];
    long long sum; //计算总流量
    int s,t; //s:源点 t:汇点
    int n,m;
    
    struct Edge{
        int c,f;
    }maps[maxn][maxn];
    
    int min(int a,int b){
        return a<b?a:b;
    }
    //每次先BFS,看看是否存在从源点到汇点的增广路
    bool BFS() {
        queue<int> q;
        memset(pri,0,sizeof(pri));
        pri[1]=1;
        q.push(1);
        while(!q.empty()) {
            int temp=q.front();
            q.pop();
            for(int i=1; i<=m; i++) {
                if(!pri[i] && maps[temp][i].c-maps[temp][i].f){
                    pri[i]=pri[temp]+1;
                    if(i==t)
                        return true;    //即如果可以流到汇点,直接return true
                    q.push(i);
                }
            }
        }
        //if(pri[m]>0)
        //    return true;
        return false;
    }
    
    //p表示当前节点,flow表示该节点通过的流量
    int dinic(int p,int flow){
        if(p==t){
            return flow;
        }
        int f=flow;
        //int value=0;
        for(int i=1;i<=m;i++){
            if(pri[i]==pri[p]+1 && maps[p][i].c-maps[p][i].f){
                int a=maps[p][i].c-maps[p][i].f;  //a为该边可以增加的流量
                int ff=dinic(i,min(a,flow));  //ff为路径中所有a的最小值,即为该条路中可以增加的流量
                maps[p][i].f+=ff;       //正向边
                maps[i][p].f-=ff;       //逆向边
                //value+=ff;
                flow-=ff;
                if(flow<=0)
                    break; //优化剪枝
            }
        }
        //return value;
        if(f-flow<=0)
            pri[p]=0;//如果从p点流出去的流量<=0,那么设置pri[p]的值为0,之后在dinic中就不考虑到p点的情况了。
        return f-flow;
    }
    void init(){
        for(int i=1;i<=m;i++){
            for(int j=1;j<=m;j++){
                maps[i][j].c=maps[i][j].f=0;
            }
        }
    }
    int main() {
        int a,b,c;
        s=1;
        while(scanf("%d%d",&n,&m)!=EOF){
            init();
            //memset(maps,0,sizeof(maps));
            sum=0;
            t=m;
            for(int i=1;i<=n;i++){
                scanf("%d%d%d",&a,&b,&c);
                maps[a][b].c+=c;    //该题有重边,这里要+=,不是去max
            }
            while(BFS()){
                sum+=dinic(s,INF);
            }
            printf("%I64d
    ",sum);
        }
        return 0;
    }
    View Code

    再给出一个大牛的模板:

    #include <cstdio>
    #include <queue>
    
    using namespace std;
    
    typedef int LL;
    const int N = 205;
    const int M = N << 2;
    const int INF = (int)1e9;
    
    struct Dinic {
    
        struct Edge {
            int v;
            LL cap, flow;
            Edge* next, * pair;
    
            void init(int a, LL b, Edge* e1, Edge* e2) {
                v = a, cap = b, flow = 0, next = e1, pair = e2;
            }    
        };
    
        Edge* head[N], * used[N];
        Edge* it;
        int lev[N], que[N];
        Edge E[M];
        int n, s, t;
        LL maxFlow;
    
        void init(int n, int s, int t) {
            it = E;
            this->n = n;
            this->s = s, this->t = t;
            for (int i = 0; i < n; i++)
                head[i] = 0;
        }
    
        void add(int u, int v, LL c) {
            it->init(v, c, head[u], it + 1);
            head[u] = it++;
            it->init(u, 0, head[v], it - 1);
            head[v] = it++;
        }
    
        bool bfs() {
            for (int i = 0; i < n; lev[i++] = -1);
            lev[s] = 0;
            int st = 0, ed = 0;
            que[ed++] = s;
            while (st < ed) {
                int u = que[st++];
                for (Edge* e = head[u]; e;  e = e->next) {
                    int v = e->v;
                    if (lev[v] == -1 && e->cap > e->flow) {
                        lev[v] = lev[u] + 1;
                        que[ed++] = v;
                    }
                }
            }
            return lev[t] != -1;    
        }
    
        LL dfs(int u, LL f) {
            if (u == t) return f;
            for (Edge* & e = used[u]; e; e = e->next) {
                int v = e->v;
                if (e->cap > e->flow && lev[v] == lev[u] + 1) {
                    LL tmp = dfs(v, min(e->cap - e->flow, f));
                    if (tmp > 0) {
                        e->flow += tmp;
                        e->pair->flow -= tmp;
                        return tmp;
                    }
                }
            }
            return 0;
        }
    
        void run() {
            maxFlow = 0;
            while (bfs()) {    
                for (int i = 0; i < n; i++)
                    used[i] = head[i];
                LL f = 1;
                while (f) {
                    f = dfs(s, INF);
                    maxFlow += f;
                }
            }
        }
    
    }G;
    
    int main() {
        int n, m, u, v, w;
        while (~scanf("%d%d", &m, &n)) {
            G.init(n, 0, n - 1);
            while (m--) {
                scanf("%d%d%d", &u, &v, &w);
                G.add(u - 1, v - 1, w);
            }
            G.run();
            printf("%d
    ", G.maxFlow);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    奥巴马邻居卖房的启示,彻底改变你的思维!
    CentOS7.0安装Nginx 1.7.4
    CentOS 7 下安装 Nginx
    C# 关于线程锁lock的使用方法
    内存屏障、编译屏障:
    linux环境下安装nginx步骤
    一、为什么要学习Java虚拟机?
    Linux CentOS系统上安装Eclipse
    poj 3311 Hie with the Pie (TSP问题)
    怎样初始化一个指针数组
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/4513810.html
Copyright © 2011-2022 走看看