以POJ 2289 为例。
#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; //nx为左集合数目,ny为右集合数目
int cnt;
int limit; //表示每个右集合顶点最多匹配的左集合顶点个数,也可能为数组
int first[1010];
bool vis[1010]; //寻找增广路径时的标记数组
int vylink[1010]; //表示右集合i顶点分配到左集合的顶点数
int ylink[510][1010]; //表示与右集合i顶点匹配的第j个元素
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;
}