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", n-dinic()/2);
}
}
}T;
int main() {
#ifndef ONLINE_JUDGE
freopen("IP.in", "r", stdin);
freopen("OP.out", "w", stdout);
#endif
T.solve();
return 0;
}