网络流之最大流模板

Dinic算法, 复杂度On*n*m(n是点数,m是边数),因为一般点数比边数少, 所以比EK(Om*m*n)更优一点.

int head[maxn], cnt;
int n, m, tim[maxn], s, t;
bool vis[maxn];
int d[maxn], cur[maxn];
struct Edge {
    int u, v, cap, flow;
} e[maxn*600];

vector<int> G[maxn];

void init() {
    memset(head, -1, sizeof(head));
    memset(G, 0, sizeof(G));
    memset(tim, 0, sizeof(tim));
    cnt = 0;
}

void add(int u, int v, int cap, int f) {
    e[cnt].u = u;
    e[cnt].cap = cap;
    e[cnt].flow = f;
    e[cnt].v = v;
}

void AddEdge(int u, int v, int cap) {
    add(u, v, cap, 0);
    G[u].push_back(cnt++);   //G[i][j] = 存的是边的编号.
    add(v, u, 0, 0);
    G[v].push_back(cnt++);
}

bool BFS() {
    memset(vis, 0, sizeof(vis));
    queue<int> q;
    q.push(s);
    vis[s] = 1;
    d[s] = 0;
    while (!q.empty()) {
        int v = q.front(); q.pop();
        for (int i = 0; i < G[v].size(); i++) {
            //直接引用, 如果是赋值的话就不能代替这样写了.
            Edge &te = e[G[v][i]];   //为了方便,这里的te就相当于是e[G[v][i]]了,这样写
            //就为了后面的方便好写.
            if (!vis[te.v] && te.cap > te.flow) { //只考虑残量网络的弧
                vis[te.v] = 1;
                d[te.v] = d[v] + 1;  //分层
                q.push(te.v);
            }
        }
    }
    return vis[t];
}

int dfs(int x, int a) {
    if (x == t || a == 0) return a;   //a?
    int flow = 0, f;
    for (int &i = cur[x]; i < G[x].size(); i++) { //从上次考虑的弧
        Edge &te = e[G[x][i]];
        if (d[x] + 1 == d[te.v] && (f = dfs(te.v, min(a, te.cap - te.flow))) > 0) {
            te.flow += f;
            e[G[x][i]^1].flow -= f;//因为加边的时候可以知道反向弧与原弧在链接表中的关系.刚好可以用^1来表示.
            flow += f;
            a -= f;
            if (a == 0) break;
        }
    }
    return flow;
}

int Dinic() {
    int flow = 0;
    while (BFS()) {
        memset(cur, 0, sizeof(cur));
        flow += dfs(s, inf);   //a的inf不能设太大. 一般设为1e9. 否则会T.
    }
    return flow;
}

你可能感兴趣的:(板子)