就是比二分图匹配多一个, 把牛放中间, 食物和饮料放两边, 然后就是用一个牛拷贝一份, 这样防止多分牛奶或者食物流到同一只牛的地方, 然后每一条边的权值是1
//SPA #include <cstring> #include <cstdio> #include <queue> #include <algorithm> #define CLR(arr, val) memset(arr, val, sizeof(arr)) #pragma warning(disable:4996) using namespace std; const int MaxV = 10000; const int MaxE = 10000 << 1; const int INF = 1e9; struct Graph { struct Vertex { int head; }V[MaxV]; struct Edge { int v, c, f, next; Edge(){} Edge(int v,int c, int f, int next):v(v), c(c), f(f), next(next){} }E[MaxE]; void init() { top = 0; CLR(V, -1); } void addEdge(int u, int v,int w) { E[top] = Edge(v, w, 0, V[u].head); V[u].head = top++; E[top] = Edge(u, 0, 0, V[v].head); V[v].head = top++; } int top; }; int h[MaxV]; //高度 int path[MaxV]; //回路 int gap[MaxV]; //gap优化 int cur[MaxV]; //当前弧优化 int s, t; int vexNum, edgeNum; Graph g; void setHeight() { CLR(gap, 0); CLR(h, -1); h[t] = 0; queue<int>Q; Q.push(t); while(!Q.empty()) { int top = Q.front(); gap[ h[top] ]++; for(int i = g.V[top].head; i != -1; i = g.E[i].next) { int v = g.E[i].v; if(h[v] == -1) { h[v] = h[top] + 1; Q.push(v); } } Q.pop(); } } int sap() { setHeight(); int maxFlow = 0, u = s; int flow = INF; for(int i = 0; i <= vexNum; i++) cur[i] = g.V[i].head; while(h[s] < vexNum) { int &i = cur[u]; for(; i != -1; i = g.E[i].next) { int v = g.E[i].v; if(g.E[i].c > g.E[i].f && h[u] == h[v] + 1) { u = v; path[v] = i; flow = min(flow, g.E[i].c - g.E[i].f); if(u == t) { while(u != s) { int j = path[u]; g.E[j].f += flow; g.E[j ^ 1].f -= flow; u = g.E[j ^ 1].v; } maxFlow += flow; flow = INF; } break; } } if(i == -1) { if(--gap[ h[u] ] == 0) break; int minH = vexNum - 1; cur[u] = g.V[u].head; for(int j = g.V[u].head; j != -1; j = g.E[j].next) if(g.E[j].c > g.E[j].f) minH = min(minH, h[g.E[j].v]); h[u] = minH + 1; ++gap[ h[u] ]; if(u != s) u = g.E[path[u] ^ 1].v; } } return maxFlow; } int N, F, D; void buildMap() { for(int i = 1; i <= F; i++) g.addEdge(0, i, 1); for(int i = F + 1; i <= F + N; i++) g.addEdge(i, i + N, 1); for(int i = F + N * 2 + 1; i <= F + N * 2 + D; i++) g.addEdge(i, vexNum, 1); int f, d; for(int i = 1; i <= N; i++) //n头牛 { scanf("%d %d", &f, &d); while(f--) { int v; scanf("%d", &v); g.addEdge(v, F + i, 1); } while(d--) { int v; scanf("%d", &v); g.addEdge(F + N + i, F + 2* N + v, 1); } } } int main() { while(scanf("%d %d %d", &N, &F, &D) != EOF) { g.init(); vexNum = F + 2 * N + D + 1; buildMap(); s = 0, t = vexNum; printf("%d\n", sap()); } return 0; }