思路:
二分+最大流。
实现:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <limits.h> 4 #include <string.h> 5 #include <assert.h> 6 #include <queue> 7 #include <vector> 8 #include <algorithm> 9 #include <iostream> 10 #include <sstream> 11 12 #define N (1500 + 2) 13 #define M (N * N + 4 * N) 14 15 typedef long long LL; 16 17 using namespace std; 18 19 struct edge 20 { 21 int v, cap, next; 22 }; 23 edge e[M]; 24 25 int head[N], level[N], cur[N]; 26 int num_of_edges; 27 28 /* 29 * When there are multiple test sets, you need to re-initialize before each 30 */ 31 void dinic_init(void) 32 { 33 num_of_edges = 0; 34 memset(head, -1, sizeof(head)); 35 return; 36 } 37 38 int add_edge(int u, int v, int c1, int c2) 39 { 40 int& i = num_of_edges; 41 42 assert(c1 >= 0 && c2 >= 0 && c1 + c2 >= 0); // check for possibility of overflow 43 e[i].v = v; 44 e[i].cap = c1; 45 e[i].next = head[u]; 46 head[u] = i++; 47 48 e[i].v = u; 49 e[i].cap = c2; 50 e[i].next = head[v]; 51 head[v] = i++; 52 return i; 53 } 54 55 void print_graph(int n) 56 { 57 for (int u = 0; u < n; u++) 58 { 59 printf("%d: ", u); 60 for (int i = head[u]; i >= 0; i = e[i].next) 61 { 62 printf("%d(%d)", e[i].v, e[i].cap); 63 } 64 printf(" "); 65 } 66 return; 67 } 68 69 /* 70 * Find all augmentation paths in the current level graph 71 * This is the recursive version 72 */ 73 int dfs(int u, int t, int bn) 74 { 75 if (u == t) return bn; 76 int left = bn; 77 for (int &i = cur[u]; i >= 0; i = e[i].next) 78 { 79 int v = e[i].v; 80 int c = e[i].cap; 81 if (c > 0 && level[u] + 1 == level[v]) 82 { 83 int flow = dfs(v, t, min(left, c)); 84 if (flow > 0) 85 { 86 e[i].cap -= flow; 87 e[i ^ 1].cap += flow; 88 cur[u] = i; 89 left -= flow; 90 if (!left) break; 91 } 92 } 93 } 94 if (left > 0) level[u] = 0; 95 return bn - left; 96 } 97 98 bool bfs(int s, int t) 99 { 100 memset(level, 0, sizeof(level)); 101 level[s] = 1; 102 queue<int> q; 103 q.push(s); 104 while (!q.empty()) 105 { 106 int u = q.front(); 107 q.pop(); 108 if (u == t) return true; 109 for (int i = head[u]; i >= 0; i = e[i].next) 110 { 111 int v = e[i].v; 112 if (!level[v] && e[i].cap > 0) 113 { 114 level[v] = level[u] + 1; 115 q.push(v); 116 } 117 } 118 } 119 return false; 120 } 121 122 LL dinic(int s, int t) 123 { 124 LL max_flow = 0; 125 126 while (bfs(s, t)) 127 { 128 memcpy(cur, head, sizeof(head)); 129 max_flow += dfs(s, t, INT_MAX); 130 } 131 return max_flow; 132 } 133 134 vector<int> v[N]; 135 int n, m; 136 bool check(int x) 137 { 138 dinic_init(); 139 for (int i = 1; i <= n; i++) 140 { 141 for (int j = 0; j < v[i].size(); j++) 142 { 143 add_edge(i, v[i][j] + n + 1, 1, 0); 144 } 145 } 146 for (int i = 1; i <= n; i++) 147 add_edge(0, i, 1, 0); 148 for (int j = n + 1; j <= n + m; j++) 149 { 150 add_edge(j, n + m + 1, x, 0); 151 } 152 return dinic(0, n + m + 1) == n; 153 } 154 155 int main() 156 { 157 while (cin >> n >> m, n || m) 158 { 159 getchar(); 160 string s, name; 161 int group; 162 for (int i = 1; i <= n; i++) v[i].clear(); 163 for (int i = 1; i <= n; i++) 164 { 165 getline(cin, s); 166 stringstream ss(s); 167 ss >> name; 168 while (ss >> group) 169 { 170 v[i].push_back(group); 171 } 172 } 173 int l = 0, r = n, ans = n; 174 while (l <= r) 175 { 176 int m = (l + r) >> 1; 177 if (check(m)) 178 { 179 r = m - 1; ans = m; 180 } 181 else l = m + 1; 182 } 183 cout << ans << endl; 184 } 185 return 0; 186 }