网络流算法模板

  • EK
//EK算法
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;

const int N = 210,INF = (int)1e9;
int n,m,tot;
int head[N],pre[N],res[N];
queue<int > que;
struct node{
    int to,w,nxt;
}e[N << 1];

inline void init(){
    while(!que.empty()) que.pop();
    for(int i = 1; i <= n; ++i) res[i] = 0;
}

inline void add(int u,int v,int w){
    e[tot].to = v; e[tot].w = w; e[tot].nxt = head[u]; head[u] = tot++;
}

bool bfs(int s,int t){
    init();
    pre[s] = -1;
    res[s] = INF;
    que.push(s);
    int now,to;
    while(!que.empty()){
        now = que.front(); que.pop();
        for(int o = head[now]; ~o; o = e[o].nxt){
            to = e[o].to;
            if(!res[to] && e[o].w){
                pre[to] = o;
                res[to] = min(e[o].w, res[now]);
                if(to == t) return true;
                que.push(to);
            }
        }
    }
    return false;
}

int EK(int s,int t){
    int ans = 0;
    while(bfs(s,t)){
        for(int o = pre[t]; ~o; o = pre[e[o^1].to]){
            e[o].w -= res[t];
            e[o^1].w += res[t];
        }
        ans += res[t];
    }
    return ans;
}

int main(){

    int u,v,w;
    while(~scanf("%d%d",&m,&n)){
        for(int i = 1; i <= n; ++i) head[i] = -1; tot = 0;
        for(int i = 1; i <= m; ++i){
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w); add(v,u,0);
        }
        printf("%d\n",EK(1,n));
    }

    return 0;
}
  • dinic
//Dinic算法
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;

const int N = 10010,M = 100010,inf = (int)1e9;
int n,m,s,t,tot;
int head[N],lev[N];
queue<int > que;
struct node{
    int to,w,nxt;
}e[M<<1];

inline void add(int u,int v,int w){
    e[tot].to = v; e[tot].w = w; e[tot].nxt = head[u]; head[u] = tot++;
}

inline void init(){
    while(!que.empty()) que.pop();
    for(int i = 1; i <= n; ++i) lev[i] = 0;
}

bool bfs(int s,int t){
    lev[s] = 1;
    que.push(s);
    int now,to;
    while(!que.empty()){
        now = que.front(); que.pop();
        if(now == t) return true;
        for(int o = head[now]; ~o; o = e[o].nxt){
            to = e[o].to;
            if(!lev[to] && e[o].w){
                lev[to] = lev[now] + 1;
                que.push(to);
            }
        }
    }
    return false;
}

int dfs(int now,int flow,int t){
    if(now == t) return flow;
    int to,sum = 0,tmp;
    for(int o = head[now]; ~o; o = e[o].nxt){
        to = e[o].to;
        if(e[o].w && lev[now] == lev[to] - 1){
            tmp = dfs(to,min(flow - sum, e[o].w),t);
            e[o].w -= tmp; e[o^1].w += tmp;
            if((sum += tmp) == flow) return sum;
        }
    }
    return sum;
}

int main(){

    int u,v,w;
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i = 1; i <= n; ++i) head[i] = -1;
    for(int i = 1; i <= m; ++i){
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w); add(v,u,0);
    }
    int ans = 0;
    while(bfs(s,t)){
        ans += dfs(s,inf,t);
        init();
    }
    printf("%d\n",ans);

    return 0;
}
  • 最小费用最大流
//最小费用最大流
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;

const int N = (int)5e3+100,M = (int)5e4+100,INF = (int)1e9;
int n,m,s,t,tot;
int head[N],pre[N],dis[N],vis[N];
queue<int > que;
struct node{
    int to,nxt,cap,cost,flow;
}e[M << 1];

inline void add(int u,int v,int cap,int cost,int flow){
    e[tot].to = v;
    e[tot].cap = cap;
    e[tot].cost = cost;
    e[tot].flow = flow;
    e[tot].nxt = head[u];
    head[u] = tot++;
}

inline void init(){
    for(int i = 1; i <= n; ++i){
        vis[i] = false;
        dis[i] = INF;
        pre[i] = -1;
    }
    while(!que.empty()) que.pop();
}

bool spfa(int s,int){
    init();
    vis[s] = true; dis[s] = 0; que.push(s);
    int now,to;
    while(!que.empty()){
        now = que.front(); que.pop();
        vis[now] = false;
        for(int o = head[now]; ~o; o = e[o].nxt){
            to = e[o].to;
            if(e[o].cap > e[o].flow && dis[to] > dis[now] + e[o].cost){
                dis[to] = dis[now] + e[o].cost;
                pre[to] = o;
                if(!vis[to]){
                    vis[to] = true; que.push(to);
                }
            }
        }
    }
    if(pre[t] == -1) return false;
    else return true;
}

int mcmf(int s,int t,int& min_cost){

    int max_flow = 0,_min = INF;
    while(spfa(s,t)){
        _min = INF;
        for(int o = pre[t]; ~o; o = pre[e[o^1].to]){
            _min = min(_min,e[o].cap - e[o].flow);
        }
        for(int o = pre[t]; ~o; o = pre[e[o^1].to]){
            e[o].flow += _min;
            e[o^1].flow -= _min;
        }
        min_cost += dis[t]*_min;
        max_flow += _min;
    }
    return max_flow;
}

int main(){

    int u,v,cap,cost,min_cost = 0;
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i = 1; i <= n; ++i) head[i] = -1; tot = 0;
    for(int i = 1; i <= m; ++i){
        scanf("%d%d%d%d",&u,&v,&cap,&cost);
        add(u,v,cap,cost,0);
        add(v,u,0,-cost,0);
    }
    cout << mcmf(s,t,min_cost) << " " << min_cost << endl;

    return 0;
}