poj 3281 Dining(最大流基础,拆点)

来源:互联网 发布:软件测试招聘信息 编辑:程序博客网 时间:2024/05/21 18:36

题意:
。。。
思路:
因为food和drink要么同时要,要不都不要,则需要把它们串起来,牛放中间
对牛进行拆点以限制每头牛吃了一份food,和一份drink

const int inf = INT_MAX/2;const int Maxn = 100000;const int MaxV = 500;struct Edge {    int to, cap, rev;};vector<Edge> G[MaxV+5];int level[MaxV+5], iter[MaxV+5]; // 距离标号,当前边// 在残量网络里面加边void add_edge(int from, int to, int cap) {    G[from].push_back( (Edge){to, cap, G[to].size()} );    G[to].push_back( (Edge){from, 0, G[from].size()-1} );}// bfs 构建层次void bfs(int s) {    memset(level, -1, sizeof(level));    level[s] = 0;    queue<int> q;    q.push(s);    while (!q.empty()) {        int u = q.front();q.pop();        int sz = G[u].size();        for (int i=0;i<sz;++i) {            Edge &e = G[u][i];            if (e.cap > 0 && level[e.to] < 0) {                level[e.to] = level[u] + 1;                q.push(e.to);            }        }    }}int dfs(int x, int t, int f) {    //cout << "go " << x << endl;    if (x == t || f == 0) return f;    int flow = 0, sz = G[x].size();    for (int &i = iter[x]; i<sz;++i) {        Edge &e = G[x][i];        if (e.cap > 0 && level[x] < level[e.to]) {            int d = dfs(e.to, t, min (f, e.cap));            if (d > 0) {                e.cap -= d;                G[e.to][e.rev].cap += d;                flow += d;                f -= d;                if (!f) break;            }        }    }    return flow;}int max_flow(int s, int t) {    int flow = 0;    for (;;) {        bfs (s);        if (level[t] < 0) return flow;        memset(iter, 0, sizeof(iter));        flow += dfs(s, t, inf);    }    return flow;}int N, F, D, tot;// 牛i拆成i, i+N, food-i-i+N-drink// food i: i+2*N, drink i: i+2*N+Fint main() {#ifndef ONLINE_JUDGE    freopen("input.in", "r", stdin);#endif    SPEED_UP    cin >> N >> F >> D;    tot = 2*N+F+D;    rep(i, 1, N) {        int x, y, z;        cin >> x >> y;        rep(j, 1, x) {            cin >> z;            add_edge(z+2*N, i, 1);        }        rep(j, 1, y) {            cin >> z;            add_edge(i+N, z+2*N+F, 1);        }    }    // 每头牛自身拆点    rep(i, 1, N) {        add_edge(i, i+N, 1);    }    // 超级源点0    rep(i, 1, F) add_edge(0, i+2*N, 1);    // 超级汇点tot+1    rep(i, 1, D) add_edge(i+2*N+F, tot+1, 1);    int _max = max_flow(0, tot+1);    cout << _max << endl;    return 0;}
0 0
原创粉丝点击