二分+二分图多重匹配。
1 /* 1669 */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #include <vector> 9 #include <deque> 10 #include <algorithm> 11 #include <cstdio> 12 #include <cmath> 13 #include <ctime> 14 #include <cstring> 15 #include <climits> 16 #include <cctype> 17 #include <cassert> 18 #include <functional> 19 #include <iterator> 20 #include <iomanip> 21 using namespace std; 22 //#pragma comment(linker,"/STACK:102400000,1024000") 23 24 #define sti set<int> 25 #define stpii set<pair<int, int> > 26 #define mpii map<int,int> 27 #define vi vector<int> 28 #define pii pair<int,int> 29 #define vpii vector<pair<int,int> > 30 #define rep(i, a, n) for (int i=a;i<n;++i) 31 #define per(i, a, n) for (int i=n-1;i>=a;--i) 32 #define clr clear 33 #define pb push_back 34 #define mp make_pair 35 #define fir first 36 #define sec second 37 #define all(x) (x).begin(),(x).end() 38 #define SZ(x) ((int)(x).size()) 39 #define lson l, mid, rt<<1 40 #define rson mid+1, r, rt<<1|1 41 42 const int maxn = 1005; 43 const int maxm = 505; 44 bool M[maxn][maxm]; 45 bool visit[maxm]; 46 int can[maxm][maxm]; 47 int sz[maxm]; 48 int n, gn, bound; 49 50 bool dfs(int u) { 51 rep(i, 0, gn) { 52 if (M[u][i] && !visit[i]) { 53 visit[i] = true; 54 if (sz[i] < bound) { 55 can[i][sz[i]++] = u; 56 return true; 57 } 58 rep(j, 0, sz[i]) { 59 if (dfs(can[i][j])) { 60 can[i][j] = u; 61 return true; 62 } 63 } 64 } 65 } 66 67 return false; 68 } 69 70 bool judge(int bound_) { 71 bound = bound_; 72 memset(sz, 0, sizeof(sz)); 73 rep(i, 0, n) { 74 memset(visit, false, sizeof(visit)); 75 if (!dfs(i)) 76 return false; 77 } 78 79 return true; 80 } 81 82 void solve() { 83 int l, r, mid; 84 int ans; 85 86 l = 0; 87 ans = r = n; 88 while (l <= r) { 89 mid = (l + r) >> 1; 90 if (judge(mid)) { 91 ans = mid; 92 r = mid - 1; 93 } else { 94 l = mid + 1; 95 } 96 } 97 98 printf("%d ", ans); 99 } 100 101 int main() { 102 ios::sync_with_stdio(false); 103 #ifndef ONLINE_JUDGE 104 freopen("data.in", "r", stdin); 105 freopen("data.out", "w", stdout); 106 #endif 107 108 char name[20]; 109 int gid; 110 char ch; 111 112 while (scanf("%d %d", &n, &gn)!=EOF && (n||gn)) { 113 memset(M, false, sizeof(M)); 114 rep(i, 0, n) { 115 scanf("%s", name); 116 while (1) { 117 scanf("%d%c", &gid, &ch); 118 M[i][gid] = true; 119 if (ch == ' ') 120 break; 121 } 122 } 123 solve(); 124 } 125 126 #ifndef ONLINE_JUDGE 127 printf("time = %d. ", (int)clock()); 128 #endif 129 130 return 0; 131 }
二分+网络流Dinic也可以解。
1 /* 1669 */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #include <vector> 9 #include <deque> 10 #include <algorithm> 11 #include <cstdio> 12 #include <cmath> 13 #include <ctime> 14 #include <cstring> 15 #include <climits> 16 #include <cctype> 17 #include <cassert> 18 #include <functional> 19 #include <iterator> 20 #include <iomanip> 21 using namespace std; 22 //#pragma comment(linker,"/STACK:102400000,1024000") 23 24 #define sti set<int> 25 #define stpii set<pair<int, int> > 26 #define mpii map<int,int> 27 #define vi vector<int> 28 #define pii pair<int,int> 29 #define vpii vector<pair<int,int> > 30 #define rep(i, a, n) for (int i=a;i<n;++i) 31 #define per(i, a, n) for (int i=n-1;i>=a;--i) 32 #define clr clear 33 #define pb push_back 34 #define mp make_pair 35 #define fir first 36 #define sec second 37 #define all(x) (x).begin(),(x).end() 38 #define SZ(x) ((int)(x).size()) 39 #define lson l, mid, rt<<1 40 #define rson mid+1, r, rt<<1|1 41 42 typedef struct { 43 int v, c, nxt; 44 } Edge_t; 45 46 const int INF = 0x3f3f3f3f; 47 const int maxn = 1005; 48 const int maxm = 505; 49 const int maxv = maxn + maxm; 50 const int maxe = maxn*maxm*2+5; 51 Edge_t E[maxe]; 52 int F[maxe]; 53 int head[maxv], head_[maxv]; 54 int id[maxm]; 55 int dis[maxv], Q[maxv]; 56 int m; 57 int n, gn; 58 int s, t; 59 60 void init() { 61 memset(head, -1, sizeof(head)); 62 m = 0; 63 s = 0; 64 t = n + gn + 1; 65 } 66 67 void addEdge(int u, int v, int c) { 68 E[m].v = v; 69 E[m].c = c; 70 E[m].nxt = head[u]; 71 head[u] = m++; 72 73 E[m].v = u; 74 E[m].c = 0; 75 E[m].nxt = head[v]; 76 head[v] = m++; 77 } 78 79 bool bfs() { 80 int l = 0, r = 0; 81 int u, v, k; 82 83 Q[r++] = s; 84 memset(dis, 0, sizeof(dis)); 85 dis[s] = 1; 86 87 while (l < r) { 88 u = Q[l++]; 89 for (k=head[u]; k!=-1; k=E[k].nxt) { 90 v = E[k].v; 91 if (!dis[v] && E[k].c>F[k]) { 92 dis[v] = dis[u] + 1; 93 if (v == t) 94 return false; 95 Q[r++] = v; 96 } 97 } 98 } 99 100 return true; 101 } 102 103 int dfs(int u, int val) { 104 if (u==t || val==0) 105 return val; 106 107 int ret = 0; 108 int tmp, v; 109 110 for (int& k=head_[u]; k!=-1; k=E[k].nxt) { 111 v = E[k].v; 112 if (dis[v]==dis[u]+1 && E[k].c>F[k] && (tmp=dfs(v, min(val, E[k].c-F[k])))>0) { 113 F[k] += tmp; 114 F[k^1] -= tmp; 115 ret += tmp; 116 val -= tmp; 117 if (val == 0) 118 break; 119 } 120 } 121 122 return ret; 123 } 124 125 int Dinic() { 126 int ret = 0, tmp; 127 128 while (1) { 129 if (bfs()) 130 break; 131 132 memcpy(head_, head, sizeof(head)); 133 while (1) { 134 tmp = dfs(s, INF); 135 if (tmp == 0) 136 break; 137 ret += tmp; 138 } 139 } 140 #ifndef ONLINE_JUDGE 141 printf("Dinic = %d ", ret); 142 #endif 143 return ret; 144 } 145 146 bool judge(int bound) { 147 rep(i, 1, gn+1) 148 E[id[i]].c = bound; 149 memset(F, 0, sizeof(F)); 150 151 return Dinic()>=n; 152 } 153 154 void solve() { 155 int l = 0, r = n, mid; 156 int ans = -1; 157 158 while (r >= l) { 159 mid = (l + r) >> 1; 160 if (judge(mid)) { 161 ans = mid; 162 r = mid - 1; 163 } else { 164 l = mid + 1; 165 } 166 } 167 168 printf("%d ", ans); 169 } 170 171 int main() { 172 ios::sync_with_stdio(false); 173 #ifndef ONLINE_JUDGE 174 freopen("data.in", "r", stdin); 175 freopen("data.out", "w", stdout); 176 #endif 177 178 char name[25]; 179 char ch; 180 int gid; 181 182 while (scanf("%d %d", &n, &gn)!=EOF && (n||gn)) { 183 init(); 184 rep(i, 1, n+1) { 185 scanf("%s", name); 186 while (1) { 187 scanf("%d%c", &gid, &ch); 188 addEdge(i, gid+n+1, 1); 189 if (ch == ' ') 190 break; 191 } 192 } 193 rep(i, 1, n+1) 194 addEdge(s, i, 1); 195 rep(i, 1, gn+1) { 196 id[i] = m; 197 addEdge(n+i, t, 1); 198 } 199 solve(); 200 } 201 202 203 #ifndef ONLINE_JUDGE 204 printf("time = %d. ", (int)clock()); 205 #endif 206 207 return 0; 208 }