多重匹配:一对多的二分图的多重匹配。二分图的多重匹配算法的实现类似于匈牙利算法,对于集合X中的元素xi,找到一个与其相连的元素yi后,检查匈牙利算法的两个条件是否成立,若yi未被匹配,则将
xi,yi匹配。否则,如果与yi匹配的元素已经达到上限,那么在所有与yi匹配的元素中选择一个元素,检查是否能找到一条增广路径,如果能,则让出位置,让xi与yi匹配。
match[i][j]表示X集合中的Xi点与y集合中的j个点相连接(一对多)
#include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<set> #include<map> #include<string> #include<cstring> #include<stack> #include<queue> #include<vector> #include<cstdlib> #define lson (rt<<1),L,M #define rson (rt<<1|1),M+1,R #define M ((L+R)>>1) #define cl(a,b) memset(a,b,sizeof(a)); #define LL long long #define P pair<int,int> #define X first #define Y second #define pb push_back #define fread(zcc) freopen(zcc,"r",stdin) #define fwrite(zcc) freopen(zcc,"w",stdout) using namespace std; const int maxn=1005; const int inf=999999; char s[100005]; vector<int> G[maxn]; int Nx,limit,cnt[maxn];//cnt数组是记录X集合Xi点 目前已经匹配Y集合里的点的个数 int matching[maxn][505];//这个表示X集合的Xi点与Y集合的cnt个点相连接 bool vis[maxn]; bool dfs(int u){//多重匹配和二分图的一般匹配差不多,还是两个条件 int N=G[u].size(); for(int i=0;i<N;i++){ int v=G[u][i]; if(vis[v])continue; vis[v]=true; if(cnt[v]<limit){ matching[v][cnt[v]++]=u;//没有达到上限,匹配 return true; }else { for(int i=0;i<cnt[v];i++){//达到上限,继续查看是否还能找到增广路 if(dfs(matching[v][i])){ matching[v][i]=u; return true; } } } } return false; } bool hungar(){ cl(cnt,0); for(int i=0;i<Nx;i++){ cl(vis,false); if(!dfs(i))return false; } return true; } int main(){ int n,m; while(scanf("%d%d",&n,&m)&&(n||m)){ getchar(); for(int i=0;i<n;i++){ gets(s); int len=strlen(s); for(int j=0;j<len;j++){ if(s[j]>='0'&&s[j]<='9'){ int num=0; while(s[j]>='0'&&s[j]<='9'){ num=num*10+s[j]-'0'; j++; } G[i].pb(num); } } } Nx=n; int l=0,r=n; while(l<r){///二分答案 // printf("%d %d \n",l,r); limit=(l+r)/2; if(hungar()){ r=limit; } else { l=limit+1; } } printf("%d\n",r); for(int i=0;i<maxn;i++)G[i].clear(); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU1669 Jamie's Contact Groups (二分+二分图的多重匹配)
时间: 2024-10-03 02:03:19