题目 http://poj.org/problem?id=2289
这是我做的第一个 多重匹配 所以参考哦 别人代码 感觉不错
http://www.cnblogs.com/-sunshine/archive/2012/08/30/2664310.html
其实这个多重匹配有点像匈牙利算法 思想是一样的
题意:给定一个规模为n的名单,要将名单中的人归到m个组中,给出每个人可能的分组号,需要确定一种分配方案,是的最大规模的组最小。
思路:一对多的二分图的多重匹配。二分图的多重匹配算法的实现类似于匈牙利算法,对于集合C中的元素xi,找到一个与其相连的元素yi后,检查匈牙利算法的两个条件是否成立,若yi未被匹配,则将
xi,yi匹配。否则,如果与yi匹配的元素已经达到上限,那么在所有与yi匹配的元素中选择一个元素,检查是否能找到一条增广路径,如果能,则让出位置,让xi与yi匹配。
二分求出limit,知道找到可以构成多重匹配的最小限制limit,在main函数中二分搜索。
ac代码
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define max 2001 bool map[max][max]; bool mark[max]; int link[max]; int cy[max][max]; int n,m,mid; //n表示列表长度 m表示分配组数 bool findpath(int u) { int i,j; for(i=0;i<m;i++) { if(map[u][i]&&!mark[i]) { mark[i]=1; if(link[i]<mid) { cy[i][link[i]++]=u; return true; } for(j=0;j<link[i];j++) { if(findpath(cy[i][j])) { cy[i][j]=u; return true; } } } } return false; } bool maxmatch() { int i,j; memset(link,0,sizeof(link)); for(i=0;i<n;i++) { memset(mark,false,sizeof(mark)); if(!findpath(i)) return false; } return true; } int main() { int i,j,v; char len[1020]; while(cin>>n>>m,n+m) { getchar(); memset(map,false,sizeof(map)); // memset(link,false,sizeof(link)); for(i=0;i<n;i++) { cin.getline(len,1020); int k=strlen(len); for(j=0;j<=k;j++) { if(len[j]>='0'&&len[j]<='9') { v=0; while(len[j]>='0'&&len[j]<='9') { v=v*10+len[j++]-'0'; } map[i][v]=1; } } } int left=0,right=n; while(left<right) { mid=(left+right)/2; if(maxmatch()) right=mid; else left=mid+1; } cout<<right<<endl; } return 0; }