题意:
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 == ' ') 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 ", R); } return 0; }