大意不再赘述。
思路:二分图最大多重匹配,可用二分枚举实现。呜呜呜,有一个BUG害我找了好久哦。。。
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <map> #include <queue> #include <stack> using namespace std; const int MAXN = 1010; const int MAXM = 1010*510; struct Edge { int v; int next; }edge[MAXM]; int nx, ny; int cnt; int limit; int first[1010]; bool vis[1010]; int vylink[1010]; int ylink[510][1010]; void init() { cnt = 0; memset(first, -1, sizeof(first)); } void read_graph(int u, int v) { edge[cnt].v = v; edge[cnt].next = first[u], first[u] = cnt++; } int find(int u) { int i, j; for(int e = first[u]; e != -1; e = edge[e].next) { i = edge[e].v; if(!vis[i]) { vis[i] = 1; if(vylink[i] < limit) { ylink[i][vylink[i]++] = u; return 1; } for(j = 0; j < vylink[i]; j++) if(find(ylink[i][j])) { ylink[i][j] = u; return 1; } } } return 0; } bool MulMatch() { memset(vylink, 0, sizeof(vylink)); for(int i = 0; i < nx; i++) { memset(vis , 0, sizeof(vis)); if(!find(i)) return 0; } return 1; } void BSearch() { int x = 0, y = nx; while(x <= y) { limit = (x+y)/2; if(MulMatch()) y = limit-1; else x = limit+1; } printf("%d\n", x); } void read_case() { init(); char str[3020]; for(int i = 0; i < nx; i++) { gets(str); for(int j = 0; j < strlen(str); j++) if(isdigit(str[j])) { // for(int j = 0; str[j]; j++) 报错了,scanf("%s", str)才能用 int v = 0; while(isdigit(str[j])) { v = v*10 + str[j++]-'0'; } read_graph(i, v); } } } void solve() { read_case(); BSearch(); } int main() { while(scanf("%d%d%*c", &nx, &ny) && (nx || ny)) { solve(); } return 0; }