题目链接(POJ):http://poj.org/problem?id=2289
题目链接(HDU):http://acm.hdu.edu.cn/showproblem.php?pid=1669
题意是Jamie有n个联系人,他现在要把这些人都分成组,现在已知每个人的可以分的分组,然后要求分组后最小化最大组的大小,也就是有一个limit,使得所有组的人数不大于limit,求出limit的最小值。
思路就是我们可以通过二分去枚举limit这个值,然后跑二分图多重匹配判断当前limit是否符合要求就好了。刚开始用链式前向星写system error,然后改成了邻接矩阵...(其实二分图的点不多,邻接矩阵就够用)
AC代码:
// #include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#define maxn 1010
// #define maxm 505
using namespace std;
struct Link{
int cnt;
int k[maxn];
}link[maxn];
bool maps[maxn][maxn];
bool vis[maxn];
int n,m,xx;
char str[20],ch;
void init(){
memset(maps,false,sizeof(maps));
}
bool dfs(int u, int limit){
for(int i=1;i<=m;i++){
if(vis[i] == false && maps[u][i] == true){
vis[i] = true;
if(link[i].cnt < limit){
link[i].k[ ++ link[i].cnt ] = u;
return true;
}
for(int j=1;j<=link[i].cnt;j++){
if(dfs(link[i].k[j], limit)){
link[i].k[j] = u;
return true;
}
}
}
}
return false;
}
bool solve(int limit){
memset(link,0,sizeof(link));
for(int i=1;i<=n;i++){
memset(vis,false,sizeof(vis));
if(!dfs(i, limit)) return false;
}
return true;
}
int main()
{
while(~scanf("%d%d",&n,&m)){
if(n == 0 && m == 0) break;
init();
for(int i=1;i<=n;i++){
scanf("%s",str);
while(1){
scanf("%d%c",&xx, &ch);
maps[i][xx + 1] = true;
if(ch == '\n') break;
}
}
int l = 1, r = n, mid, ans = n;
while(l <= r){
mid = (l + r) >> 1;
if(solve(mid)){
r = mid - 1;
ans = mid;
}
else{
l = mid + 1;
}
}
printf("%d\n", ans);
}
return 0;
}