题目 http://acm.hdu.edu.cn/showproblem.php?pid=2063
这是我第一个匹配题目 刚开始的时候不知道怎么做 百度上找了一下资料 有些不错 有些看不懂哦
所以我自己写一点自己体会 这个是基础知识哦
二分图的基本概念
一个无向图G=<V, E>,如果存在两个集合X、Y,使得X∪Y=V, X∩Y=Φ,并且每一条边e={x,y}有x∈X,y∈Y,则称G为一个二分图(bipartite graph)。常用<X, E, Y>来表示一个二分图。若对X中任一x及Y中任一y恰有一边e∈E,使e = {x, y}, 则称G为完全二分图(complete bipartite graph)。当|X| = m,|Y| = n时,完全二分图G记为Km,n。
二分图的性质:
定理:无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶数。
匹配:设G=<V, E>为二分图,如果M⊆E,并且M中没有任何两边有公共端点。M=Φ时称M为空匹配。
最大匹配:G的所有匹配中边数最多的匹配称为最大匹配。
完全匹配:若X(Y)中所有的顶点都是匹配M中的端点。则成M为完全匹配。若M既是X-完全匹配又是Y-完全匹配,则称M为G的完全匹配。
注意:最大匹配总是存在但未必唯一;X(Y)-完全匹配及G的完全匹配必定是最大的,但反之则不然;X(Y)-完全匹配未必存在。
现在我来解释一下什么叫增广路径哦 先看二张表哦
若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径。(M为一个匹配)
由增广路的定义可以推出下述三个结论:
1-P的路径长度必定为奇数,第一条边和最后一条边都不属于M。
2-将M和P进行异或操作(去同存异)可以得到一个更大的匹配M’。
3-M为G的最大匹配当且仅当不存在M的增广路径。
然后匈牙利算法是 每次找出一条增广路径来 直到找不到为止哦。。。
下面附上我ac代码哦
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define max 501
bool map[max][max]; ///二分图
bool mark[max]; ///寻找增广路径时的标志数组
int cx[max],cy[max]; ///cx表示左集合 cy表示右集合
int k,m,n; ///m表示女生的人数左集合,n表示男生的人数右集合
int findpath(int u)
{
int i,j;
for(i=1;i<=n;i++)
{
if(map[u][i]&&!mark[i])
{
mark[i]=1;
if(cy[i]==-1||findpath(cy[i]))
{
cy[i]=u;
cx[u]=i;
return 1;
}
}
}
return 0;
}
int maxmattch()
{
int res=0;
int i,j;
for(i=1;i<=m;i++)
cx[i]=-1;
for(j=1;j<=n;j++)
cy[j]=-1;
for(i=1;i<=m;i++)
{
if(cx[i]==-1)
{
for(j=1;j<=n;j++)
mark[j]=0;
res+=findpath(i);
}
}
return res;
}
int main()
{
int i,j,nx,ny;
while(cin>>k,k)
{
memset(map,false,sizeof(map));
memset(mark,false,sizeof(mark));
cin>>m>>n;
for(i=0;i<k;i++)
{
cin>>nx>>ny;
map[nx][ny]=1;
}
int h=maxmattch();
cout<<h<<endl;
}
return 0;
}