模板从  这里   搬运,链接博客还有很多网络流题集题解参考。

最大流模板 ( 可处理重边 )

;
const int INF = 0x3f3f3f3f;

struct Edge
{
    int from,to,cap,flow;
    Edge(){}
    Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow){}
};

struct Dinic
{
    int n,m,s,t;            //结点数,边数(包括反向弧),源点与汇点编号
    vector<Edge> edges;     //边表 edges[e]和edges[e^1]互为反向弧
    vector<int> G[maxn];    //邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
    bool vis[maxn];         //BFS使用,标记一个节点是否被遍历过
    int d[maxn];            //d[i]表从起点s到i点的距离(层次)
    int cur[maxn];          //cur[i]表当前正访问i节点的第cur[i]条弧

    void init(int n,int s,int t)
    {
        this->n=n,this->s=s,this->t=t;
        ;i<=n;i++) G[i].clear();
        edges.clear();
    }

    void AddEdge(int from,int to,int cap)
    {
        edges.push_back( Edge() );
        edges.push_back( Edge(to,,) );
        m = edges.size();
        G[);
        G[to].push_back(m-);
    }

    bool BFS()
    {
        memset(vis,,sizeof(vis));
        queue<int> Q;//用来保存节点编号的
        Q.push(s);
        d[s]=;
        vis[s]=true;
        while(!Q.empty())
        {
            int x=Q.front(); Q.pop();
            ; i<G[x].size(); i++)
            {
                Edge& e=edges[G[x][i]];
                if(!vis[e.to] && e.cap>e.flow)
                {
                    vis[e.to]=true;
                    d[e.to] = d[x]+;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }

    //a表示从s到x目前为止所有弧的最小残量
    //flow表示从x到t的最小残量
    int DFS(int x,int a)
    {
        )return a;
        ,f;//flow用来记录从x到t的最小残量
        for(int& i=cur[x]; i<G[x].size(); i++)
        {
            Edge& e=edges[G[x][i]];
            ==d[e.to] && (f=DFS( e.to,min(a,e.cap-e.flow) ) )> )
            {
                e.flow +=f;
                edges[G[x][i]^].flow -=f;
                flow += f;
                a -= f;
                ) break;
            }
        }
        ;///炸点优化
        return flow;
    }

    int Maxflow()
    {
        ;
        while(BFS())
        {
            memset(cur,,sizeof(cur));
            flow += DFS(s,INF);
        }
        return flow;
    }
}DC;

Dinic

#include<bits/stdc++.h>
using namespace std;
;
;///边要是题目规定的两倍
const int INF = 0x3f3f3f3f;

struct edge{ int to,cap,tot,rev; };
struct DINIC{
    int n,m;
    edge w[maxm];
    int fr[maxm];
    int num[maxn],cur[maxn],first[maxn];
    edge e[maxm];
    void init(int n){
        memset(cur,,sizeof(cur));
        this->n=n;
        m=;
    }
    void AddEdge(int from,int to,int cap){
        w[++m]=(edge){to,cap};
        num[from]++,fr[m]=from;
        w[++m]=(edge){};
        num[to]++,fr[m]=to;
    }
    void prepare(){
        first[]=;
        ;i<=n;i++)
            first[i]=first[i-]+num[i-];
        ;i<n;i++)
            num[i]=first[i+]-;
        num[n]=m;
        ;i<=m;i++){
            e[first[fr[i]]+(cur[fr[i]]++)]=w[i];

            )){
                e[first[fr[i]]+cur[fr[i]]-].rev=first[w[i].to]+cur[w[i].to]-;
                e[first[w[i].to]+cur[w[i].to]-].rev=first[fr[i]]+cur[fr[i]]-;
            }
        }
    }
    int q[maxn];
    int dist[maxn];
    int t;
    bool bfs(int s){
        ,r=;
        q[]=s;
        memset(dist,-,(n+)*);
        dist[s]=;
        while(l<=r){
            int u=q[l++];
            for(int i=first[u];i<=num[u];i++){
                int v=e[i].to;
                ) || (!e[i].cap))
                    continue;
                dist[v]=dist[u]+;
                if (v==t)
                    return true;
                q[++r]=v;
            }
        }
        ;
    }
    int dfs(int u,int flow){
        if (u==t)
            return flow;
        ;
        for(int& i=cur[u];i<=num[u];i++){
            int v=e[i].to;
            )
                continue;
            int t=dfs(v,min(flow,e[i].cap));
            if (t){
                e[i].cap-=t;
                e[e[i].rev].tot+=t;
                flow-=t;
                ans+=t;
                if (!flow)
                    return ans;
            }
        }
        return ans;
    }
    int MaxFlow(int s,int t){
        ;
        this->t=t;
        while(bfs(s)){
            do{
                memcpy(cur,first,(n+)*);
                int flow;
                while(flow=dfs(s,INF))
                    ans+=flow;
            }while(bfs(s));
            ;i<=m;i++)
                e[i].cap+=e[i].tot,e[i].tot=;
        }
        return ans;
    }
}DC;

int main(void)
{
    int N, M, S, T;
    while(~scanf("%d %d %d %d", &N, &M, &S, &T)){
        DC.init(N);
        while(M--){
            int u, v, w;
            scanf("%d %d %d", &u, &v, &w);
            DC.AddEdge(u, v, w);
        }
        DC.prepare();
        printf("%d", DC.MaxFlow(S, T));
    }
    ;
}

Dinic(这个快一点、点下标从1开始)

///这个是找到的别人的代码
///我见过的最快的最大流代码了
///但是我不知道原理,所以只能套一套这样子....
#include <bits/stdc++.h>

;
const int INF = INT_MAX;

struct Node {
    int v, f, index;
    Node(int v, int f, int index) : v(v), f(f), index(index) {}
};

int n, m, s, t;
std::vector<Node> edge[MAXN];
std::vector<int> list[MAXN], height, count, que, excess;
typedef std::list<int> List;
std::vector<List::iterator> iter;
List dlist[MAXN];
int highest, highestActive;
typedef std::vector<Node>::iterator Iterator;

inline void init()
{
    ; i<=n; i++)
        edge[i].clear();
}

inline void addEdge(const int u, const int v, const int f) {
    edge[u].push_back(Node(v, f, edge[v].size()));
    edge[v].push_back(Node(u, , edge[u].size() - ));
}

inline void globalRelabel(int n, int t) {
    height.assign(n, n);
    height[t] = ;
    count.assign(n, );
    que.clear();
    que.resize(n + );
    , qt = ;
    for (que[qt++] = t; qh < qt;) {
        ;
        for (Iterator p = edge[u].begin(); p != edge[u].end(); ++p) {
            ) {
                count[height[p->v] = h]++;
                que[qt++] = p->v;
            }
        }
    }
    ; i <= n; i++) {
        list[i].clear();
        dlist[i].clear();
    }
    ; u < n; ++u) {
        if (height[u] < n) {
            iter[u] = dlist[height[u]].insert(dlist[height[u]].begin(), u);
            ) list[height[u]].push_back(u);
        }
    }
    highest = (highestActive = height[que[qt - ]]);
}

inline void push(int u, Node &e) {
    int v = e.v;
    int df = std::min(excess[u], e.f);
    e.f -= df;
    edge[v][e.index].f += df;
    excess[u] -= df;
    excess[v] += df;
     < excess[v] && excess[v] <= df) list[height[v]].push_back(v);
}

inline void discharge(int n, int u) {
    int nh = n;
    for (Iterator p = edge[u].begin(); p != edge[u].end(); ++p) {
        ) {
            ) {
                push(u, *p);
                ) return;
            } else {
                nh = std::min(nh, height[p->v] + );
            }
        }
    }
    int h = height[u];
    ) {
        for (int i = h; i <= highest; i++) {
            for (List::iterator it = dlist[i].begin(); it != dlist[i].end();
                 ++it) {
                count[height[*it]]--;
                height[*it] = n;
            }
            dlist[i].clear();
        }
        highest = h - ;
    } else {
        count[h]--;
        iter[u] = dlist[h].erase(iter[u]);
        height[u] = nh;
        if (nh == n) return;
        count[nh]++;
        iter[u] = dlist[nh].insert(dlist[nh].begin(), u);
        highest = std::max(highest, highestActive = nh);
        list[nh].push_back(u);
    }
}

inline int hlpp(int n, int s, int t) {
    ;
    highestActive = ;
    highest = ;
    height.assign(n, );
    height[s] = n;
    iter.resize(n);
    ; i < n; i++)
        if (i != s)
            iter[i] = dlist[height[i]].insert(dlist[height[i]].begin(), i);
    count.assign(n, );
    count[] = n - ;
    excess.assign(n, );
    excess[s] = INF;
    excess[t] = -INF;
    ; i < (int)edge[s].size(); i++) push(s, edge[s][i]);
    globalRelabel(n, t);
    ;) {
        if (list[highestActive].empty()) {
            highestActive--;
            continue;
        }
        u = list[highestActive].back();
        list[highestActive].pop_back();
        discharge(n, u);
        // if (--res == 0) globalRelabel(res = n, t);
    }
    return excess[t] + INF;
}

int main() {
    while(~scanf("%d %d %d %d", &n, &m, &s, &t)){
        init();
        , u, v, f; i < m; i++) {
            scanf("%d %d %d", &u, &v, &f);
            addEdge(u, v, f);
        }
        printf(, s, t));///点是1~n范围的话,貌似要 n+1
    }
    ;
}

Highest Label Preflow Push(快到没人性)

最小费用最大流模板

点都是 0~N-1 

struct Edge
{
    int from,to,cap,flow,cost;
    Edge(){}
    Edge(int f,int t,int c,int fl,int co):from(f),to(t),cap(c),flow(fl),cost(co){}
};  

struct MCMF
{
    int n,m,s,t;
    vector<Edge> edges;
    vector<int> G[maxn];
    bool inq[maxn];     //是否在队列
    int d[maxn];        //Bellman_ford单源最短路径
    int p[maxn];        //p[i]表从s到i的最小费用路径上的最后一条弧编号
    int a[maxn];        //a[i]表示从s到i的最小残量  

    //初始化
    void init(int n,int s,int t)
    {
        this->n=n, this->s=s, this->t=t;
        edges.clear();
        ;i<n;++i) G[i].clear();
    }  

    //添加一条有向边
    void AddEdge(int from,int to,int cap,int cost)
    {
        edges.push_back(Edge(,cost));
        edges.push_back(Edge(to,,,-cost));
        m=edges.size();
        G[);
        G[to].push_back(m-);
    }  

    //求一次增广路
    bool BellmanFord(int &flow, int &cost)
    {
        ;i<n;++i) d[i]=INF;
        memset(inq,,sizeof(inq));
        d[s]=, a[s]=INF, inq[s]=;
        queue<int> Q;
        Q.push(s);
        while(!Q.empty())
        {
            int u=Q.front(); Q.pop();
            inq[u]=false;
            ;i<G[u].size();++i)
            {
                Edge &e=edges[G[u][i]];
                if(e.cap>e.flow && d[e.to]>d[u]+e.cost)
                {
                    d[e.to]= d[u]+e.cost;
                    p[e.to]=G[u][i];
                    a[e.to]= min(a[u],e.cap-e.flow);
                    if(!inq[e.to]){ Q.push(e.to); inq[e.to]=true; }
                }
            }
        }
        if(d[t]==INF) return false;
        flow +=a[t];
        cost +=a[t]*d[t];
        int u=t;
        while(u!=s)
        {
            edges[p[u]].flow += a[t];
            edges[p[u]^].flow -=a[t];
            u = edges[p[u]].from;
        }
        return true;
    }  

    //求出最小费用最大流
    int Min_cost()
    {
        ,cost=;
        while(BellmanFord(flow,cost));
        return cost;
    }
}MM;  
struct Edge
{
    int from,to,cap,flow,cost;
    Edge(int u,int v,int ca,int f,int co):from(u),to(v),cap(ca),flow(f),cost(co){};
};

struct MCMF
{
    int n,m,s,t;
    vector<Edge> edges;
    vector<int> G[maxn];
    int inq[maxn];//是否在队列中
    int d[maxn];//距离
    int p[maxn];//上一条弧
    int a[maxn];//可改进量

    void init(int n)//初始化
    {
        this->n=n;
        ;i<=n;i++)
            G[i].clear();
        edges.clear();
    }

    void AddEdge(int from,int to,int cap,int cost)//加边
    {
        edges.push_back(Edge(,cost));
        edges.push_back(Edge(to,,,-cost));
        int m=edges.size();
        G[);
        G[to].push_back(m-);
    }

    bool SPFA(int s,int t,int &flow,int &cost)//寻找最小费用的增广路,使用引用同时修改原flow,cost
    {
        ;i<n;i++)
            d[i]=INF;
        memset(inq,,sizeof(inq));
        d[s]=;inq[s]=;p[s]=;a[s]=INF;
        queue<int> Q;
        Q.push(s);
        while(!Q.empty())
        {
            int u=Q.front();
            Q.pop();
            inq[u]--;
            ;i<G[u].size();i++)
            {
                Edge& e=edges[G[u][i]];
                if(e.cap>e.flow && d[e.to]>d[u]+e.cost)//满足可增广且可变短
                {
                    d[e.to]=d[u]+e.cost;
                    p[e.to]=G[u][i];
                    a[e.to]=min(a[u],e.cap-e.flow);
                    if(!inq[e.to])
                    {
                        inq[e.to]++;
                        Q.push(e.to);
                    }
                }
            }
        }
        if(d[t]==INF) return false;//汇点不可达则退出
        flow+=a[t];
        cost+=d[t]*a[t];
        int u=t;
        while(u!=s)//更新正向边和反向边
        {
            edges[p[u]].flow+=a[t];
            edges[p[u]^].flow-=a[t];
            u=edges[p[u]].from;
        }
        return true;
    }

    int MincotMaxflow(int s,int t)
    {
        ,cost=;
        while(SPFA(s,t,flow,cost));
        return cost;
    }
}MM;

网络流的知识可以参考《挑战程序设计竞赛Ⅱ》 or 以下链接

链接链接Ⅱ链接Ⅲ链接IV

最大流 && 最小费用最大流模板的更多相关文章

  1. [模板]网络最大流 & 最小费用最大流

    我的作业部落有学习资料 可学的知识点 Dinic 模板 #define rg register #define _ 10001 #define INF 2147483647 #define min(x ...

  2. BZOJ 1834: [ZJOI2010]network 网络扩容(最大流+最小费用最大流)

    第一问直接跑最大流.然后将所有边再加一次,费用为扩容费用,容量为k,再从一个超级源点连一条容量为k,费用为0的边到原源点,从原汇点连一条同样的边到超级汇点,然  后跑最小费用最大流就OK了. ---- ...

  3. bzoj 1834: [ZJOI2010]network 网络扩容【最大流+最小费用最大流】

    第一问直接跑最大流即可.建图的时候按照费用流建,费用为0. 对于第二问,在第一问dinic剩下的残量网络上建图,对原图的每条边(i,j),建(i,j,inf,cij),表示可以用c的花费增广这条路.然 ...

  4. 洛谷P2604 最大流+最小费用最大流

    题目链接:https://www.luogu.org/problem/P2604 题目描述 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在 ...

  5. POJ - 2516 Minimum Cost(最小费用最大流)

    1.K种物品,M个供应商,N个收购商.每种物品从一个供应商运送到一个收购商有一个单位运费.每个收购商都需要K种物品中的若干.求满足所有收购商需求的前提下的最小运费. 2.K种物品拆开来,分别对每种物品 ...

  6. P3381 【模板】最小费用最大流

    P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行 ...

  7. Doctor NiGONiGO’s multi-core CPU(最小费用最大流模板)

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=693 题意:有一个 k 核的处理器和 n 个工作,全部的工作都须要在一个核上处理一个单位的 ...

  8. 【网络流#2】hdu 1533 - 最小费用最大流模板题

    最小费用最大流,即MCMF(Minimum Cost Maximum Flow)问题 嗯~第一次写费用流题... 这道就是费用流的模板题,找不到更裸的题了 建图:每个m(Man)作为源点,每个H(Ho ...

  9. 图论算法-最小费用最大流模板【EK;Dinic】

    图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...

随机推荐

  1. Linux(Ubuntu)常用命令 & vim基本操作

    Linux先知: Linux历史: 关于这个我就不再多说了,其实是一个很有意思的故事串,网上找下一大堆. 类Unix系统目录结构: ubuntu没有盘符这个概念,只有一个根目录/,所有文件都在它下面 ...

  2. pandas 数据排序.sort_index()和.sort_values()

    原文链接:https://www.jianshu.com/p/f0ed06cd5003 import pandas as pd df = pd.DataFrame(……) 说明:以下“df”为Data ...

  3. 使用Oracle12c 以上的PDB创建数据库用户 密码过期的简单处理

    1. 先通过监听查看PDB的名字 Windows 打开命令行: 输入命令 lsnrctl status 一般在如图示的最下面 2. 也可以通过GS的全局配置文件来查看 数据库连接SID信息. C:\P ...

  4. qt undefined reference to `vtable for subClass'

    1. 建立一个console工程 QT -= gui CONFIG += c++ console CONFIG -= app_bundle # The following define makes y ...

  5. 偶遇com组件 .rc 文件 not found .tlb文件问题:

    好久木有弄com组件来,记忆已经模糊了,今天遇见一个编译问题,折腾了半天,mark一下: xxx_x64.rc(273): error RC2135: file not found: xxx.tlb ...

  6. MySQL总结(3)

    ORDER BY 与 GROUP BY ORDER BY GROUP BY 排序产生的输出 分组行.但输出可能不是分组的顺序 不一定需要 如果与聚集函数一起使用列(或表达式)则必须使用 任意列都可以使 ...

  7. RabbitMq学习6-安装php-amqplib(RabbitMQ的phpAPI)

    一.使用composer安装php-amqplib 1.在你的项目中添加一个 composer.json文件: { "require": { "php-amqplib/p ...

  8. Kafka在windows下的配置使用

    Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(partition).多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实时的处理大量 ...

  9. [转载]ISE中COE与MIF文件的联系与区别

    原文地址:ISE中COE与MIF文件的联系与区别作者:铁掌北京漂 在ISE中,当用Blcok Memory Generator 生成某个ROM模块时,经常要对ROM中的内容作初始化.这时,就需要我们另 ...

  10. linux 源码安装postgresql

    下载源码包 --安装所需要的系统软件包 yum groupinstall -y "Development tools" yum install -y bison flex read ...