2013-team4/code/network-flow

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

{{{
Dinic 最大流
FL 为流量类型,可以修改,MAXN 为最大点数
}}}
{{{
创建
Dinic D;
清除全图
D.clear_graph();
清除图中流量
D.clear_flow();
从 from 到 to 添加一条容量为 cap 的边
D.add_edge(from, to, cap);
从 s 到 t 计算最大流
D.max_flow(s, t);
}}}
{{{
typedef long long FL;
const int MAXN = 20005;
const FL INF = 2100000000;

struct Edge{
    int from, to;
    FL cap, flow;
    Edge(int fr, int t, FL c, FL fl){
        from = fr; to = t; cap = c; flow = fl;
    }
};
struct Dinic{
    vector<int> G[MAXN];
    vector<Edge> E;
    int s, t;
    int cur[MAXN], d[MAXN];
    void clear_graph(){
        E.clear();
        for(int i = 0; i < MAXN; i++)
            G[i].clear();
    }
    void clear_flow(){
        for(int i = 0; i < E.size(); i++)
            E[i].flow = 0;
    }
    void add_edge(int from, int to, FL cap){
        int m = E.size();
        E.push_back(Edge(from, to, cap, 0));
        E.push_back(Edge(to, from, 0, 0));
        G[from].push_back(m);
        G[to].push_back(m + 1);
    }
    bool bfs(){
        bool vis[MAXN];
        memset(vis, 0, sizeof(vis));
        queue<int> Q;
        Q.push(s); d[s] = 0; vis[s] = 1;
        while(!Q.empty()){
            int x = Q.front(); Q.pop();
            for(int i = 0; i < G[x].size(); i++){
                Edge &e = E[G[x][i]];
                if(vis[e.to] == 0 && e.cap > e.flow){
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    FL dfs(int x, FL mi){
        if(x == t || mi == 0) return mi;
        FL sum = 0;
        for(int &i = cur[x]; i < G[x].size(); i++){
            Edge &e = E[G[x][i]];
            if(d[x] + 1 == d[e.to]){
                FL f = dfs(e.to, min(mi, e.cap - e.flow));
                if(f > 0){
                    e.flow += f;
                    E[G[x][i] ^ 1].flow -= f;
                    sum += f;
                    mi -= f;
                    if(mi == 0) break;
                }
            }
        }
        return sum;
    }
    FL max_flow(int s, int t){
        this->s = s; this->t = t;
        FL flow = 0;
        while(bfs()){
            memset(cur, 0, sizeof(cur));
            flow += dfs(s, INF);
        }
        return flow;
    }
};
}}}
{{{
//网络流模板dinic+sap   by zimpha
//经过POJ 3469测试
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=20010;
const int MAXM=600000;
const int inf=1000000000;

struct Edge {
    int v, flow;
    Edge *next, *op;
}mem[MAXM];

Edge *E[MAXN], *cur[MAXN], *cnt;
int pre[MAXN], dis[MAXN], gap[MAXN];
int N, M, S, T, NN;


inline void addedge(int u, int v, int a, int b) {
    cnt->v=v; cnt->flow=a; cnt->next=E[u]; E[u]=cnt++;
    cnt->v=u; cnt->flow=b; cnt->next=E[v]; E[v]=cnt++;
    E[u]->op=E[v]; E[v]->op=E[u];
}

int sap() {
    int maxflow=0, aug=inf, u, v;
    for (int i=0; i<NN; i++) cur[i]=E[i], gap[i]=dis[i]=0;
    gap[S]=NN; u=pre[S]=S;
    while (dis[S]<NN) {
        bool flag=false;
        for (Edge *&p=cur[u]; p; p=p->next) 
            if (p->flow>0 && dis[u]==dis[v=p->v]+1) {
                flag=true;
                if (p->flow<aug) aug=p->flow;
                pre[v]=u; u=v;
                if (u==T) {
                    maxflow+=aug;
                    while (u!=S) {
                        u=pre[u];
                        cur[u]->flow-=aug;
                        cur[u]->op->flow+=aug;
                    }
                    aug=inf;
                }
                break;
            }
        if (flag) continue;
        int mindis=NN;
        for (Edge *p=E[u]; p; p=p->next) 
            if (p->flow>0 && dis[p->v]<mindis) {
                mindis=dis[p->v]; cur[u]=p;
            }
        if ((--gap[dis[u]])==0) break;
        gap[dis[u]=mindis+1]++; u=pre[u];
    }
    return maxflow;
}

int level[MAXN], Q[MAXN];

bool dinic_bfs() {
    memset(level, -1, sizeof(level));
    level[S]=0; Q[0]=S;
    for (int h=0, t=1; h<t; h++) {
        int u=Q[h], v;
        for (Edge *p=E[u]; p; p=p->next) 
            if (level[v=p->v]==-1 && p->flow>0) {
                level[v]=level[u]+1;
                Q[t++]=v;
            }
    }
    return (level[T]!=-1);
}

int dinic_dfs(int u, int low) {
    if (u==T) return low;
    int ret=0, tmp, v;
    for (Edge *p=E[u]; p && ret<low; p=p->next) 
        if (level[v=p->v]==level[u]+1 && p->flow>0) {
            if (tmp=dinic_dfs(v, min(low-ret, p->flow))) {
                ret+=tmp, p->flow-=tmp, p->op->flow+=tmp;
            }
        }
    if (!ret) level[u]=-1; return ret;
}

int dinic() {
    int maxflow=0, t;
    while (dinic_bfs()) {
        while (t=dinic_dfs(S, inf)) maxflow+=t;
    }
    return maxflow;
}

void init() {
    memset(E, 0, sizeof(E));
    S=0; T=N+1; NN=N+2; cnt=mem;
}

int main() {
    init();
    return 0;
}
}}}
Dinic 最大流
FL 为流量类型,可以修改,MAXN 为最大点数
创建
Dinic D;
清除全图
D.clear_graph();
清除图中流量
D.clear_flow();
从 from 到 to 添加一条容量为 cap 的边
D.add_edge(from, to, cap);
从 s 到 t 计算最大流
D.max_flow(s, t);
typedef long long FL;
const int MAXN = 20005;
const FL INF = 2100000000;
struct Edge{
    int from, to;
    FL cap, flow;
    Edge(int fr, int t, FL c, FL fl){
        from = fr; to = t; cap = c; flow = fl;
    }
};
struct Dinic{
    vector<int> G[MAXN];
    vector<Edge> E;
    int s, t;
    int cur[MAXN], d[MAXN];
    void clear_graph(){
        E.clear();
        for(int i = 0; i < MAXN; i++)
            G[i].clear();
    }
    void clear_flow(){
        for(int i = 0; i < E.size(); i++)
            E[i].flow = 0;
    }
    void add_edge(int from, int to, FL cap){
        int m = E.size();
        E.push_back(Edge(from, to, cap, 0));
        E.push_back(Edge(to, from, 0, 0));
        G[from].push_back(m);
        G[to].push_back(m + 1);
    }
    bool bfs(){
        bool vis[MAXN];
        memset(vis, 0, sizeof(vis));
        queue<int> Q;
        Q.push(s); d[s] = 0; vis[s] = 1;
        while(!Q.empty()){
            int x = Q.front(); Q.pop();
            for(int i = 0; i < G[x].size(); i++){
                Edge &e = E[G[x][i]];
                if(vis[e.to] == 0 && e.cap > e.flow){
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    FL dfs(int x, FL mi){
        if(x == t || mi == 0) return mi;
        FL sum = 0;
        for(int &i = cur[x]; i < G[x].size(); i++){
            Edge &e = E[G[x][i]];
            if(d[x] + 1 == d[e.to]){
                FL f = dfs(e.to, min(mi, e.cap - e.flow));
                if(f > 0){
                    e.flow += f;
                    E[G[x][i] ^ 1].flow -= f;
                    sum += f;
                    mi -= f;
                    if(mi == 0) break;
                }
            }
        }
        return sum;
    }
    FL max_flow(int s, int t){
        this->s = s; this->t = t;
        FL flow = 0;
        while(bfs()){
            memset(cur, 0, sizeof(cur));
            flow += dfs(s, INF);
        }
        return flow;
    }
};
//网络流模板dinic+sap   by zimpha
//经过POJ 3469测试
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=20010;
const int MAXM=600000;
const int inf=1000000000;
struct Edge {
    int v, flow;
    Edge *next, *op;
}mem[MAXM];
Edge *E[MAXN], *cur[MAXN], *cnt;
int pre[MAXN], dis[MAXN], gap[MAXN];
int N, M, S, T, NN;
inline void addedge(int u, int v, int a, int b) {
    cnt->v=v; cnt->flow=a; cnt->next=E[u]; E[u]=cnt++;
    cnt->v=u; cnt->flow=b; cnt->next=E[v]; E[v]=cnt++;
    E[u]->op=E[v]; E[v]->op=E[u];
}
int sap() {
    int maxflow=0, aug=inf, u, v;
    for (int i=0; i<NN; i++) cur[i]=E[i], gap[i]=dis[i]=0;
    gap[S]=NN; u=pre[S]=S;
    while (dis[S]<NN) {
        bool flag=false;
        for (Edge *&p=cur[u]; p; p=p->next) 
            if (p->flow>0 && dis[u]==dis[v=p->v]+1) {
                flag=true;
                if (p->flow<aug) aug=p->flow;
                pre[v]=u; u=v;
                if (u==T) {
                    maxflow+=aug;
                    while (u!=S) {
                        u=pre[u];
                        cur[u]->flow-=aug;
                        cur[u]->op->flow+=aug;
                    }
                    aug=inf;
                }
                break;
            }
        if (flag) continue;
        int mindis=NN;
        for (Edge *p=E[u]; p; p=p->next) 
            if (p->flow>0 && dis[p->v]<mindis) {
                mindis=dis[p->v]; cur[u]=p;
            }
        if ((--gap[dis[u]])==0) break;
        gap[dis[u]=mindis+1]++; u=pre[u];
    }
    return maxflow;
}
int level[MAXN], Q[MAXN];
bool dinic_bfs() {
    memset(level, -1, sizeof(level));
    level[S]=0; Q[0]=S;
    for (int h=0, t=1; h<t; h++) {
        int u=Q[h], v;
        for (Edge *p=E[u]; p; p=p->next) 
            if (level[v=p->v]==-1 && p->flow>0) {
                level[v]=level[u]+1;
                Q[t++]=v;
            }
    }
    return (level[T]!=-1);
}
int dinic_dfs(int u, int low) {
    if (u==T) return low;
    int ret=0, tmp, v;
    for (Edge *p=E[u]; p && ret<low; p=p->next) 
        if (level[v=p->v]==level[u]+1 && p->flow>0) {
            if (tmp=dinic_dfs(v, min(low-ret, p->flow))) {
                ret+=tmp, p->flow-=tmp, p->op->flow+=tmp;
            }
        }
    if (!ret) level[u]=-1; return ret;
}
int dinic() {
    int maxflow=0, t;
    while (dinic_bfs()) {
        while (t=dinic_dfs(S, inf)) maxflow+=t;
    }
    return maxflow;
}
void init() {
    memset(E, 0, sizeof(E));
    S=0; T=N+1; NN=N+2; cnt=mem;
}
int main() {
    init();
    return 0;
}