这道题用的是匈牙利算法的性质去做的, 就跟迭代加深一样, 有一个搜索的层数限制, 这里的限制是每个点的最多可以存在几条路径,一但搜到符合条件的, 存在限制最小的情况, 这个层数就是答案。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#define mem(a) memset(a, 0, sizeof(a))
#define maxn 1005
using namespace std;
int map[maxn][maxn], vis[maxn], pnum[maxn], limit[maxn], lk[maxn][maxn], n, m;
bool dfs(int a)
{
int i, j;
for(i = 1;i <= m;i++)
{
if(!vis[i]&&map[a][i])
{
vis[i] = 1;
if(lk[i][0] < limit[i])
{
lk[i][++lk[i][0]] = a;// lk[i][0]代表这个点存放路径的个数
return true;
}
for(j = 1;j <= lk[i][0];j++)
{
if(dfs(lk[i][j]))
{
lk[i][j] = a;
return true;
}
}
}
}
return false;
}
bool check(int mid)
{
int i;
for(i = 1;i <= m;i++)
{
limit[i] = min(mid, pnum[i]);
}
mem(lk);
for(i = 1;i <= n;i++)
{
mem(vis);
if(!dfs(i))
return false;
}
return true;
}
int main(int argc, char *argv[])
{
int i, j, k, low, high, mid;
for(;;)
{
mem(map);
mem(vis);
mem(pnum);
mem(limit);
mem(lk);
scanf("%d%d",&n, &m);
if(n == 0&&m == 0)
break;
for(i = 1;i <= n;i++)
{
scanf("%*s");
while(1)
{
scanf("%d", &j);
pnum[j + 1]++;
map[i][j + 1] = 1;
if(getchar() == '\n')
break;
}
}
low = 0, high = n;
while(low < high)
{
mid = (low + high) / 2;
if(check(mid))
high = mid;
else
low = mid + 1;
}
printf("%d\n", high);
}
return 0;
}