好像多重匹配一般是用网络流来做的。。
这是匈牙利算法的模板:lim是每个组的上界
思路是每个组都可以匹配lim个点,那么当点x遇到的组匹配的点数还没有超过lim时,直接匹配即可
如果已经等于了lim,这时就要从这个组的lim个点里找到一个能匹配到其他组的点(类似于普通匹配的寻找增广路过程)
int dfs(int x,int lim){ for(int i=1;i<=m;i++)//枚举每个组 if(!vis[i] && mp[x][i]){ vis[i]=1; if(match[i].size()<lim){ match[i].push_back(x); return 1; } //每个和i匹配的点 for(int j=0;j<match[i].size();j++){ if(dfs(match[i][j],lim)){ match[i][j]=x; return 1; } } } return 0; }
完整代码
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> using namespace std; #define N 2005 int n,m,mp[N][N],vis[N]; vector<int>match[N]; int dfs(int x,int lim){ for(int i=1;i<=m;i++)//枚举每个组 if(!vis[i] && mp[x][i]){ vis[i]=1; if(match[i].size()<lim){ match[i].push_back(x); return 1; } //每个和i匹配的点 for(int j=0;j<match[i].size();j++){ if(dfs(match[i][j],lim)){ match[i][j]=x; return 1; } } } return 0; } int judge(int lim){ for(int i=1;i<=n;i++)match[i].clear(); for(int i=1;i<=n;i++){ memset(vis,0,sizeof vis); if(!dfs(i,lim))return 0; } return 1; } char s[N],ch; int main(){ while(cin>>n>>m,n){ memset(mp,0,sizeof mp); for(int i=1;i<=n;i++){ scanf("%s",s); int j; while(1){ scanf("%d%c",&j,&ch); mp[i][++j]=1; if(ch=='\n')break; } } int l=0,r=2*n,mid,ans=0; while(l<=r){ mid=l+r>>1; if(judge(mid)) ans=mid,r=mid-1; else l=mid+1; } cout<<ans<<endl; } }