您的位置:首页 > 其它

POJ 2289 Jamie's Contact Groups(多重匹配+二分)

2015-08-10 17:24 429 查看
题意:
Jamie有很多联系人,但是很不方便管理,他想把这些联系人分成组,已知这些联系人可以被分到哪个组中去,而且要求每个组的联系人上限最小,即有一整数k,使每个组的联系人数都不大于k,问这个k最小是多少?
题目分析:
多重匹配,二分枚举所有极限值。
多重匹配如何匹配?
假如我们有两个集合X, Y 但是呢 Y可以匹配多个X, 这个时候我们需要给这个匹配设置一个极限值。比如Y可以匹配三个X。 假如匹配的值不到三个X我们就将他们匹配,
直到到达极限值为止。在这里Y要保存所有的与之匹配的X,若是匹配值满了,进行Find()匹配就行了。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define INF 0x3fffffff
#define maxn 1505
int n, m;
bool G[maxn][maxn], vis[maxn];
vector<vector<int> >Group;

bool Find(int u,int limt)
{
for(int i=0; i<m; i++)
{
if(G[u][i] && !vis[i])
{
vis[i] = true;
if( Group[i].size() < limt )
{
Group[i].push_back(u);
return true;
}
for(int j=0; j < Group[i].size(); j++)
{
if( Find(Group[i][j], limt) )
{
Group[i].erase(Group[i].begin()+j);
Group[i].push_back(u);
return true;
}
}
}
}
return false;
}

bool solve(int limt)
{
int num = 0;
Group.clear();
Group.resize(m+1);
for(int i=0; i<n; i++)
{
memset(vis, false, sizeof(vis));
if(Find(i, limt) )
num ++;
}
return num == n;
}

int main()
{
int a;
char ch;
while(scanf("%d %d",&n, &m), n+m)
{
memset(G, false, sizeof(G));
for(int i=0; i<n; i++)
{
scanf("%*s");
while(1)
{
// getchar();
scanf("%d%c",&a, &ch);
G[i][a] = true;
if(ch == '\n')
break;
}
}
int L = 0, R = n;
while(L < R)
{
int mid = (L + R) / 2;
if( solve(mid) )
R = mid;
else
L = mid + 1;
}
printf("%d\n", R);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: