网络流之最大流模板

来源:互联网 发布:instagram软件下载 编辑:程序博客网 时间:2024/05/18 00:56

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;}