Original title: http://poj.org/problem?id=2289
#include <cstdio> #include <cstring> #include <string> #include <queue> #include <vector> #include <map> #include <algorithm> #define INF 1e9using namespace Std;const int maxn = 2000;const int MAXM = 5100 00;int N, M, num_nodes;map<string, int>mm;vector<int>vec[maxn];struct Edge {int from, to, flow, cap; }EDGE[MAXM*2]; vector<int>g[maxn]; int edgenum; void Add (int u, int v, int c) {edge[edgenum].from = u; Edge[edgenum].to = v; Edge[edgenum].flow = 0; Edge[edgenum].cap = C; edgenum++; Edge[edgenum].from = v; edge[edgenum].to = u; Edge[edgenum].flow = 0; Edge[edgenum].cap = 0; edgenum++; G[u].push_back (edgenum-2); G[v].push_back (edgenum-1); } int DEEP[MAXN]; BOOL VIS[MAXN]; void BFS (int s, int t) {queue<int>q; Memset (Vis, false, sizeof Vis); Q.push (t); Vis[t] = true; Deep[t] = 0; while (! Q.empty ()) {int now = Q.front (); Q.pop (); for (int i = 0;i< (int) g[now].size (); i++) {int v = edge[g[now][i]].to; if (!vis[v]) {Deep[v] = Deep[now] + 1; VIS[V] = true; Q.push (v); }}}} int GAP[MAXN]; int CUR[MAXN]; int FRONT[MAXN]; int Augment (int s, int t) {int minflow = INF; int begin = T; while (begin = s) {edge& E = Edge[front[begin]]; Minflow = min (Minflow, e.cap-e.flow); begin = E.from; } begin = T; while (begin = s) {edge[front[begin]].flow + = Minflow; Edge[front[begin]^1].flow-= Minflow; begin = Edge[front[begin]].from; } return Minflow; } int Maxflow (int s, int t) {int flow = 0; BFS (S, t); memset (Gap, 0, sizeof Gap); memset (cur, 0, sizeof cur); for (int i = 0;i<num_nodes;i++) gap[deep[i]]++; int begin = s; while (Deep[s] < Num_nodes) {if (begin = = T) {flow + = Augment (s, t); begin = S; } bool flag = FALSE; for (int i = cur[begin];i< (int) g[begin].size (); i++) {edge& e = edge[g[begin][i]]; if (E.cap > E.flow && deep[begin] = = Deep[e.to] + 1) {front[e.to] = G[begin][i]; Cur[begin] = i; Flag = true; begin = E.to; Break }} if (!flag) {int k = num_nodes-1; for (int i = 0;i< (int) g[begin].size (); i++) {edge& e = edge[g[begin][i]]; if (E.cap > E.flow) k = min (k, deep[e.to]); } if (--gap[deep[begin]] = = 0) break; Gap[deep[begin] = k+1]++; Cur[begin] = 0; if (begin = s) begin = edge[front[begin]].from; }} return flow; } void Init () {for (int i = 0;i<num_nodes+2;i++) g[i].clear (); Edgenum = 0; memset (deep, 0, sizeof deep); }int Main () {while (~scanf ("%d%d", &n, &m)) {if (n = = 0 && m = = 0) break;mm.clear (); for (int i = 1;i<=n;i++) v Ec[i].clear (); int cnt = 1;char name[20];int x;for (int i = 1;i<=n;i++) {scanf ("%s", name); Mm[name] = Cnt;while (1) {scanf ( "%d", &x); Vec[cnt].push_back (x+n+1); char ch = getchar (); if (ch = = ' \ n ') break; cnt++;} int L = 0, r = n;int s = 0, t = n+m+1;int ans;num_nodes = t+1;while (l <= r) {init (); int mid = (l+r)/2;for (int i = 1;i< ; =n;i++) {Add (S, I, 1), for (int j = 0;j< (int) vec[i].size (); j + +) Add (i, vec[i][j], 1);} for (int i = n+1;i<=n+m;i++) Add (I, T, mid), int flow = Maxflow (S, t), if (flow = = N) {r = Mid-1;ans = Mid;} Elsel = mid + 1;} printf ("%d\n", ans);} return 0;}
POJ 2289--jamie ' s contact Groups two points + max flow