题目描述
RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了。可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐。但是,每个女孩都有各自的想法,举个例子把,Rabbit只愿意和XHD或PQK做partner,Grass只愿意和linle或LL做partner,PrincessSnow愿意和水域浪子或伪酷儿做partner。考虑到经费问题,boss刘决定只让找到partner的人去坐过山车,其他的人,嘿嘿,就站在下面看着吧。聪明的Acmer,你可以帮忙算算最多有多少对组合可以坐上过山车吗?
输入格式
输入数据的第一行是三个整数K , M , N,分别表示可能的组合数目,女生的人数,男生的人数。0<K<=1000
1<=N 和M<=500.接下来的K行,每行有两个数,分别表示女生Ai愿意和男生Bj做partner。最后一个0结束输入。输出格式
对于每组数据,输出一个整数,表示可以坐上过山车的最多组合数。
输入样例
6 3 3
1 1
1 2
1 3
2 1
2 3
3 1
0输出样例
3
分析
思路:将女生作为左点集(编号1~n),男生作为右点集(n+1 ~n+m)进行配对,套用匈牙利算法计算最大匹配数即可,以下分别是DFS版本和BFS版本的源代码。
源程序
DFS版本
#include <bits/stdc++.h>
#define MAXN 1005
#define MAXM 1005
using namespace std;
struct Edge{
int u,v,next;
Edge(){}
Edge(int u,int v,int next):u(u),v(v),next(next){}
}edge[MAXM];
int EdgeCount,head[MAXN];
int k,n,m,link[MAXN];
bool vis[MAXN];
void addEdge(int u,int v)
{
edge[++EdgeCount]=Edge(u,v,head[u]);
head[u]=EdgeCount;
}
bool dfs(int u)
{
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].v;
if(!vis[v]){ //不在交替路中
vis[v]=true;
if(link[v]==-1 || dfs(link[v])){ //未匹配点或找到新方案
link[v]=u;
return true;
}
}
}
return false;
}
int hargarian()
{
memset(link,-1,sizeof(link));
int ans=0; //记录匹配数
for(int i=1;i<=n;i++){
memset(vis,false,sizeof(vis));
if(dfs(i))
ans++;
}
return ans;
}
int main()
{
while(scanf("%d",&k)&&k){
memset(head,0,sizeof(head)); //初始化
EdgeCount=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=k;i++){ //建图
int u,v;
scanf("%d%d",&u,&v);
addEdge(u,v+n); //女生编号为1~n
} //男生编号为n+1~n+m
printf("%d\n",hargarian());
}
}
BFS版本
#include <bits/stdc++.h>
#define MAXN 1005
#define MAXM 1005
using namespace std;
struct Edge{
int u,v,next;
Edge(){}
Edge(int u,int v,int next):u(u),v(v),next(next){}
}edge[MAXM];
int EdgeCount,head[MAXN];
int k,n,m,pre[MAXN],link[MAXN],vis[MAXN];
queue<int> q;
void addEdge(int u,int v)
{
edge[++EdgeCount]=Edge(u,v,head[u]);
head[u]=EdgeCount;
}
int hargarian()
{
memset(pre,-1,sizeof(pre));
memset(vis,-1,sizeof(vis));
memset(link,-1,sizeof(link));
int ans=0; //记录匹配数
for(int i=1;i<=n;i++){
if(link[i]==-1){ //尚未匹配
while(!q.empty()) q.pop(); //清空队列
q.push(i);
bool flag=false;
while(!q.empty()&&!flag){ //寻找匹配方案
int u=q.front();q.pop();
for(int j=head[u];j;j=edge[j].next){
if(flag) break; //已找到匹配方案
int v=edge[j].v;
if(vis[v]!=i){ //不在交替路中
vis[v]=i;
if(link[v]>=0) //对应点已匹配
q.push(link[v]),pre[link[v]]=u;
else{ //找到匹配点
flag=true;
int l=u,r=v;
while(l!=-1){ //分配匹配方案
int tmp=link[l];
link[l]=r;
link[r]=l;
l=pre[l];
r=tmp;
}
}
}
}
}
if(link[i]!=-1) //该点有匹配
ans++;
}
}
return ans;
}
int main()
{
while(scanf("%d",&k)&&k){
memset(head,0,sizeof(head)); //初始化
EdgeCount=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=k;i++){ //建图
int u,v;
scanf("%d%d",&u,&v);
addEdge(u,n+v); //女生编号为1~n
} //男生编号为n+1~n+m
printf("%d\n",hargarian());
}
}