二分图最大匹配

二分图最大匹配顾名思义就是从二分图上做匹配且匹配数最大。(以下简称二分图匹配)

所谓二分图便是把一群点分成两个部分,同一部分的不能相互连接所组成的图便是二分图。

二分图匹配如果想要达到结果最大,那么可以采用贪心的策略。

便是如果这个点如果想要匹配的那个人已经被匹配上了,可以分两种情况讨论。

第一种就是如果你所匹配的那个人所匹配的对象还有下家,就抢过来,而那个对象便去找他的下家。

从而不断找下去。如果都能成功就可以了。要注意成功的意思不意味这你要抢的人还有匹配的对象就可以了而是你要抢的人要抢的人还有匹配的对象,有一条不满足那你也不能匹配。

当然如果本来就没有人匹配到你相匹配的人,那你很幸运,直接连就好了。

第二种就是没有成功的情况,可以想到,没有成功的情况最有可能是后面的人,所以后面的人如果不能匹配到想匹配的人的话,就只能孤独了。

接下来讲代码

先上代码

#include<iostream>
#include<cstring>
using namespace std;
int map[1005][1005];//
int visit[1005],flag[1005];//visit是有没有被访问注意是访问,不是匹配,而flag才是访问
int n2,m;//
bool dfs(int a)
{
    for(int i=1;i<=n2;i++)
    {
        if(map[a][i]&&!visit[i])//如果该节点没有被找到过 注意:在下面的循环中会清零。
        {
            visit[i]=1;//对于a来说被找到了
            if(!flag[i]||dfs(flag[i]))//如果该节点没有被匹配到或者它可以把他抢过来 (第一种情况)
            {
                flag[i]=a;//就抢过来
                return true;
            }
        }
    }
    return false;
}
int main()
{
    int n1;
    cin>>n1>>n2>>m;//n1是左边二分图的边,n2是右边二分图的边,m是边数
    memset(map,0,sizeof(map));
    for(int i=1; i<=m; i++)
    {
      int x,y;
      cin>>x>>y;
      if(y>m)//可能会出现比边数大的情况。
      continue;
      map[x][y]=1;
    }
    memset(flag,0,sizeof(flag));
    int ans=0;
    for(int i=1;i<=n1;i++)
    {
      memset(visit,0,sizeof(visit));
      if(dfs(i))
      ans++;//如果匹配到一个人就加上
    }
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2018-06-19 21:01  DAGGGGGGGGGGGG  阅读(141)  评论(0编辑  收藏  举报