[kuangbin带你飞]专题十一 网络流

const int maxn = 1e4 + 5;
const int maxm = 2e5 + 5;
struct Edge {
    int from, to, next , cap;
} edge[maxm];
int head[maxn];
int tol;
int s, t;
void init() {
    ms(head, -1);
    tol = 0;
}
void add(int u, int v, int w) {
    edge[tol].from = u;
    edge[tol].to = v;
    edge[tol].cap = w;
    edge[tol].next = head[u];
    head[u] = tol++;

    edge[tol].from = v;
    edge[tol].to = u;
    edge[tol].cap = 0;
    edge[tol].next = head[v];
    head[v] = tol++;
}
int dep[maxn];
int gap[maxn];
int q[maxn];
void bfs() {
    ms(dep, -1);
    ms(gap, 0);
    dep[t] = 0;
    gap[0] = 1;
    int l = 0, r = 0;
    q[r++] = t;
    while(l < r) {
        int u = q[l++];
        for(int i = head[u]; i != -1; i = edge[i].next) {
            int v = edge[i].to;
            int w = edge[i^1].cap;
            if(w != 0 && dep[v] == -1) {
                ++gap[dep[v] = dep[u] + 1];
                q[r++] = v;
            }
        }
    }
}
int cur[maxn], stk[maxn];
int sap(int n) {
    int res = 0;
    int top = 0;
    bfs();
    memcpy(cur, head, sizeof(head));
    int u = s, i;
    while(dep[s] < n) {
        if(u == t) {
            int Min = inf;
            int tn = n;
            for(i = 0; i < top; i++) {
                if(Min > edge[stk[i]].cap) {
                    Min = edge[stk[i]].cap;
                    tn = i;
                }
            }
            for(i = 0; i < top; i++) {
                edge[stk[i]].cap -= Min;
                edge[stk[i] ^ 1].cap += Min;
            }
            res  += Min;
            top = tn;
            u = edge[stk[tn]].from;
        }

        for(i = cur[u]; i != -1; i = edge[i].next) if(edge[i].cap != 0 && dep[u] == dep[edge[i].to] + 1)break;

        if(i != -1) {
            cur[u] = i;
            stk[top++] = i;
            u = edge[i].to;
        } else {
            if(--gap[dep[u]] == 0)break;
            int minn = n;
            for(i = head[u]; i != -1; i = edge[i].next) {
                if(edge[i].cap && minn > dep[edge[i].to]) {
                    minn = dep[edge[i].to];
                    cur[u] = i;
                }
            }
            ++gap[dep[u] = minn + 1];
            if(u != s) {
                u = edge[stk[--top]].from;
            }
        }
    }
    return res;
}
isap

B - Dining

题意比较简单,有N头牛,农场主人准备了(1 - F)F份食物和,(1 - D)D份饮料,每头牛i有自己喜欢的fi份食物和di份饮料,ai1... aif, bi1 ... bid,问你最多有几头牛能得到自己喜欢的食物和饮料

水题。建一个源点0连接所有食物i,(标号为2 * N + i) ,把全部饮料i(标号为2 * N  + F + i)连接汇点(标号N * 2+ F + D + 1),然后把每头牛i拆成两个点i,i+N,连上一条容量为1的边,再把牛i和喜欢的食物连接起来,食物 - > 牛i,再把牛i和饮料连接起来,牛i + N - > 饮料.跑一下最大流就得出答案了。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <time.h>
#include <string>
#include <stack>
#include <set>
#include <map>
#include <iostream>
#include <bitset>
#include <algorithm>
using namespace std;
#define MP make_pair
#define PB push_back
#define ms(a,b) memset((a),(b),sizeof(a))
typedef long long LL;
typedef pair<int, int> Pii;
typedef vector<int> Vi;
typedef vector<Pii> Vii;
const int inf = 0x3f3f3f3f;
const LL INF = (1uLL << 63) - 1;
const LL mod = 1000000007;
const double Pi = acos(-1.0);
const int maxn = 1e4 + 5;
const int maxm = 2e5 + 5;
struct Edge {
    int from, to, next , cap;
} edge[maxm];
int head[maxn];
int tol;
int s, t;
void init() {
    ms(head, -1);
    tol = 0;
}
void add(int u, int v, int w) {
    edge[tol].from = u;
    edge[tol].to = v;
    edge[tol].cap = w;
    edge[tol].next = head[u];
    head[u] = tol++;

    edge[tol].from = v;
    edge[tol].to = u;
    edge[tol].cap = 0;
    edge[tol].next = head[v];
    head[v] = tol++;
}
int dep[maxn];
int gap[maxn];
int q[maxn];
void bfs() {
    ms(dep, -1);
    ms(gap, 0);
    dep[t] = 0;
    gap[0] = 1;
    int l = 0, r = 0;
    q[r++] = t;
    while(l < r) {
        int u = q[l++];
        for(int i = head[u]; i != -1; i = edge[i].next) {
            int v = edge[i].to;
            int w = edge[i^1].cap;
            if(w != 0 && dep[v] == -1) {
                ++gap[dep[v] = dep[u] + 1];
                q[r++] = v;
            }
        }
    }
}
int cur[maxn], stk[maxn];
int sap(int n) {
    int res = 0;
    int top = 0;
    bfs();
    memcpy(cur, head, sizeof(head));
    int u = s, i;
    while(dep[s] < n) {
        if(u == t) {
            int Min = inf;
            int tn = n;
            for(i = 0; i < top; i++) {
                if(Min > edge[stk[i]].cap) {
                    Min = edge[stk[i]].cap;
                    tn = i;
                }
            }
            for(i = 0; i < top; i++) {
                edge[stk[i]].cap -= Min;
                edge[stk[i] ^ 1].cap += Min;
            }
            res  += Min;
            top = tn;
            u = edge[stk[tn]].from;
        }

        for(i = cur[u]; i != -1; i = edge[i].next) if(edge[i].cap != 0 && dep[u] == dep[edge[i].to] + 1)break;

        if(i != -1) {
            cur[u] = i;
            stk[top++] = i;
            u = edge[i].to;
        } else {
            if(--gap[dep[u]] == 0)break;
            int minn = n;
            for(i = head[u]; i != -1; i = edge[i].next) {
                if(edge[i].cap && minn > dep[edge[i].to]) {
                    minn = dep[edge[i].to];
                    cur[u] = i;
                }
            }
            ++gap[dep[u] = minn + 1];
            if(u != s) {
                u = edge[stk[--top]].from;
            }
        }
    }
    return res;
}
int main() {
#ifdef local
    freopen("in", "r", stdin);
    //  freopen("w","w",stdout);
#endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    init();
    int N, F, D , x;
    cin >> N >> F >> D;
    s = 0, t = N + N + F + D + 1;
    for(int i = 1; i <= F; i++) {
        add(0, i + 2 * N, 1);
    }
    for(int i = 1; i <= N; i++) {
        int f, d;
        add(i, i + N, 1);
        cin >> f >> d;
        for(int j = 0; j < f; j++) {
            cin >> x;
            add(x + 2 * N, i, 1);
        }
        for(int j = 0; j < d; j++) {
            cin >> x;
            add(i + N, x + 2 * N + F, 1);
        }
    }
    for(int i = 1; i <= D; i++) {
        add(i + 2 * N + F, t, 1);
    }
    cout << sap(t + 1) << endl;
}
View Code
原文地址:https://www.cnblogs.com/scau-zk/p/6492404.html