6 3 3 1 1 1 2 1 3 2 1 2 3 3 1 0
3
二分图匹配,可以用网络流求最小割
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<algorithm> #include<queue> using namespace std; const int maxn = 1e5 + 10; int T, n1, n2, m, x, y; struct MaxFlow { struct Edges { int end, flow; Edges(){} Edges(int end, int flow) :end(end), flow(flow){} }edge[maxn]; int first[maxn], next[maxn], dis[maxn], tot; void clear(){ tot = 0; memset(first, -1, sizeof(first)); } void AddEdge(int s, int t, int flow) { edge[tot] = Edges(t, 0); next[tot] = first[s]; first[s] = tot++; edge[tot] = Edges(s, flow); next[tot] = first[t]; first[t] = tot++; } bool bfs(int s, int t) { memset(dis, -1, sizeof(dis)); queue<int> p; p.push(s); dis[s] = 0; while (!p.empty()) { int q = p.front(); p.pop(); for (int i = first[q]; i >= 0; i = next[i]) { if (edge[i ^ 1].flow&&dis[edge[i].end] == -1) { p.push(edge[i].end); dis[edge[i].end] = dis[q] + 1; } } } return dis[t] != -1; } int dfs(int s, int t, int low) { if (s == t) return low; for (int i = first[s]; i >= 0; i = next[i]) { if (dis[s] + 1 == dis[edge[i].end] && edge[i ^ 1].flow) { int x = dfs(edge[i].end, t, min(low, edge[i ^ 1].flow)); if (x) { edge[i].flow += x; edge[i ^ 1].flow -= x; return x; } } } return 0; } int dinic(int s, int t) { int maxflow = 0, inc = 0; while (bfs(s, t)) while (inc = dfs(s, t, 0x7FFFFFFF)) maxflow += inc; return maxflow; } }solve; int main() { //scanf("%d", &T); while (scanf("%d", &m), m) { scanf("%d%d", &n1, &n2); solve.clear(); for (int i = 1; i <= n1; i++) solve.AddEdge(0, i, 1); for (int i = 1; i <= n2; i++) solve.AddEdge(n1 + i, n1 + n2 + 1, 1); while (m--) { scanf("%d%d", &x, &y); solve.AddEdge(x, n1 + y, 1); } printf("%d\n", solve.dinic(0, n1 + n2 + 1)); } return 0; }