关于二分匹配,一开始总下不了手,应该说,不知道该从何下手,课件上就很直接的就引入匈牙利算法,看了好久之后还是一样一头雾水,这让我情何以堪啊!!
不过,跟这算法走一遍之后,感觉有些许的理解这个算法了,问题的关键在与寻找增广路径,当图中不存在增广路径时,表明已经是最大匹配了
这里面的四道题目,有三道是完全的模板题,pku2239需要稍微转换一下,题目中说,在course和每周的12个教室进行匹配,不发生冲突,其实也就是总共300个courses和7*12个教室进行匹配,只需要在输入的时候稍微的修改一下,a 表示course,q days 在p class上课,即表示在mat[a][12*(p-1)+q]=1
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream>
#include<string>
#define MAXN 210
using namespace std;
bool mat[MAXN][MAXN],vis[MAXN];
int match[MAXN],vn,vm;
int path(int s)
{
for(int i=1;i<=vm;i++)
if(mat[s][i]&&!vis[i])
{
vis[i]=true;
if(match[i]==-1||path(match[i]))
{
match[i]=s;
return 1;
}
}
return 0;
}
int main()
{
int k,m,a;
while(scanf("%d %d",&vn,&vm)==2)
{
memset(match,-1,sizeof(match));
memset(mat,false,sizeof(mat));
for(int i=1;i<=vn;i++)
{
scanf("%d",&m);
for(int j=1;j<=m;j++)
{
scanf("%d",&a);
mat[i][a]=true;
}
}
int ans=0;
for(int i=1;i<=vn;i++)
{
memset(vis,0,sizeof(vis));
ans+=path(i);
}
printf("%d\n",ans);
}
return 0;
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream>
#include<string>
#define MAXN 310
using namespace std;
bool mat[110][MAXN],vis[MAXN];
int match[MAXN],vn,vm;
int path(int s)
{
for(int i=1;i<=vm;i++)
if(mat[s][i]&&!vis[i])
{
vis[i]=true;
if(match[i]==-1||path(match[i]))
{
match[i]=s;
return 1;
}
}
return 0;
}
int main()
{
int m,a,cas;
scanf("%d",&cas);
while(cas--)
{
scanf("%d %d",&vn,&vm);
memset(match,-1,sizeof(match));
memset(mat,false,sizeof(mat));
for(int i=1;i<=vn;i++)
{
scanf("%d",&m);
for(int j=1;j<=m;j++)
{
scanf("%d",&a);
mat[i][a]=true;
}
}
int ans=0;
for(int i=1;i<=vn;i++)
{
memset(vis,0,sizeof(vis));
ans+=path(i);
}
if(ans==vn)
printf("YES\n");
else printf("NO\n");
}
return 0;
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
bool mat[301][12*8],vis[12*8];
int match[12*8],n;
int path(int s)
{
for(int i=1;i<=12*7+1;i++)
if(mat[s][i]&&!vis[i])
{
vis[i]=true;
if(match[i]==-1||path(match[i]))
{
match[i]=s;
return 1;
}
}
return 0;
}
int main()
{
int t,a,b;
while(scanf("%d",&n)==1)
{
memset(mat,false,sizeof(mat));
memset(match,-1,sizeof(match));
for(int i=1;i<=n;i++)
{
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&a,&b);
mat[i][(a-1)*12+b]=1;
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
memset(vis,false,sizeof(vis));
ans+=path(i);
}
printf("%d\n",ans);
}
return 0;
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream>
#define MAXN 501
using namespace std;
int vn,vm,mat[MAXN][MAXN],match[MAXN];
bool vis[MAXN];
int path(int s)
{
for(int i=1;i<=vn;i++)
{
if(mat[s][i]&&!vis[i])
{
vis[i]=true;
if(match[i]==-1|| path(match[i]))
{
match[i]=s;
return 1;
}
}
}
return 0;
}
int main()
{
int k,a,b;
while(scanf("%d",&k)==1&&k)
{
scanf("%d %d",&vm,&vn);
memset(mat,0,sizeof(mat));
for(int i=0;i<k;i++)
{
scanf("%d %d",&a,&b);
mat[a][b]=1;
}
int ans=0;
memset(match,-1,sizeof(match));
for(int i=1;i<=vm;i++)
{
memset(vis,false,sizeof(vis));
ans+=path(i);
}
printf("%d\n",ans);
}
return 0;
}