![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; }
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 - > 饮料.跑一下最大流就得出答案了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }