POJ 1466 Girls and Boys (网络流Dinic)

从来就没有会过二分图匹配, 今天带来又一二分图匹配的水题网络流做法
跑的有点慢, 是直接dinic, 无优化, 博主暂时不会
思路:
1.建图时拆点, 将每一个人强行变成两边中的元素, one is 1~n, other is n+1~2n然后对于题目给的关系就直接两个连边,
2.由于这样求出的流量是我们把边加了两次的结果, 所以我们求出的匹配数是结果÷2, 题目求的是最大独立点集, 就用节点数-结果/2

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 1010;
const int M = 4*N*N;
const int oo = ~0U >> 1;
#define next Next
#define begin Begin
#define rep(i, s, t) for(int i = s; i <= t; ++i)
#define erep(i, u) for(int i = begin[u]; i^(-1); i = next[i])

struct Dinic {
    int S, T, n, c[M], dep[N];
    int e, begin[N], next[M], to[M];

    void init() {
        e = 0; S = 0; T = 2*n+1;
        rep(i, S, T) begin[i] = -1;
    }

    void add(int x, int y, int f) {
        to[e] = y;
        next[e] = begin[x];
        begin[x] = e;
        c[e++] = f;
    }

    void add_flow(int x, int y, int f) {
        add(x, y, f); add(y, x, 0);
    }

    queue<int> q;
    bool part() {
        rep(i, S, T) dep[i] = -1;
        q.push(S); dep[S] = 0;
        while(!q.empty()) {
            int u = q.front(), v; q.pop();
            erep(i, u)
                if(c[i]>0 && dep[v = to[i]] == -1)
                    dep[v] = dep[u]+1, q.push(v);
        }
        return dep[T] ^ (-1);
    }

    int dfs(int u, int max_flow) {
        int v, t;
        if(u == T) return max_flow;
        erep(i, u)
            if(dep[u]+1 == dep[v=to[i]] && c[i] > 0 && (t=dfs(v, min(max_flow, c[i])))) {
                c[i] -= t, c[i^1] += t;
                return t;
            }
        return 0;
    }

    int dinic(int res = 0, int t = 0) {
        while(part()) {
            while((t=dfs(S, oo)))
                res += t;
        }
        return res;
    }

    void solve() {
        while(~scanf("%d", &n)) {
            init();
            rep(i, 1, n) {
                add_flow(S, i, 1);
                char s;
                int u, len, k;
                scanf("%*d: (%d)", &len);
                while(len--) scanf("%d", &u), add_flow(i, u+n+1, 1);
                add_flow(i+n, T, 1);
            }
            printf("%d
", n-dinic()/2);
        }
    }
}T;

int main() {
#ifndef ONLINE_JUDGE
    freopen("IP.in", "r", stdin);
    freopen("OP.out", "w", stdout);
#endif
    T.solve();
    return 0;
}
原文地址:https://www.cnblogs.com/pbvrvnq/p/8530157.html