二分图最大匹配

来源:互联网 发布:我的世界java怎么安装 编辑:程序博客网 时间:2024/05/01 05:23

其实我很久之前就想写二分图的匈牙利算法,因为蛋疼的网络流算法写起来很不顺心……而且遇到某些特殊问题当然用特殊方法会有更好的效果啦。

匈牙利算法写起来还是很简单的,基本上理解了交错路之后就OK了。

我用的是邻接表实现。

算法思想:

1.置空res数组,表示全都没有匹配

2.从1到n1找增广路径,如果有的就ans++

3.对于k号找路径的话,就列出所有与k关联的顶点j,筛选出j没有在增广路径或者顶点j已经匹配的但仍然找到增广路径,j的匹配记为k。

/*******************************************************************************//* OS           : 3.2.0-58-generic #88-Ubuntu SMP Tue Dec 3 UTC 2013 GNU/Linux * Compiler     : g++ (GCC)  4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) * Encoding     : UTF8 * Date         : 2014-04-06 * All Rights Reserved by yaolong.*****************************************************************************//* Description: ********************************************************************************************************************************************//* Analysis: ***********************************************************************************************************************************************//*****************************************************************************/#include <iostream>#include <cstring>#include<vector>#include<vector>#include<cstdio>using namespace std;#define N 500int n1,n2,m; //n1为A集合数,n2为B集合数,m为边数bool stat[N];  //是否被覆盖int res[N];    //匹配点class Vertex{public:    Vertex(int n)    {        link_v.resize(n);    }    Vertex()    {    }    vector<int> link_v;};vector<Vertex> mp;bool find(int k){    vector<int> ::iterator itr=mp[k].link_v.begin();    vector<int> ::iterator itr_end=mp[k].link_v.end();    while(itr!=itr_end)    {        if(stat[*itr]==0)   //未标记=>不在增长路径        {            stat[*itr]=1;            if(res[*itr]==0   //未匹配点                    ||find(res[*itr]))   //还有增长路径            {                res[*itr]=k;    //标记*itr =k                return true;            }        }        itr++;    }    return false;}int Hungry(){    int ans=0;    memset(res,0,sizeof(res));    for(int i=1; i<=n1; i++)    {        memset(stat,0,sizeof(stat));        if(find(i)) ans++;    }    return ans;}int main(){    freopen("input.txt","r",stdin);    freopen("output.txt","w",stdout);    int t1,t2;    while(cin>>n1>>n2)    {        mp.clear();        mp.resize(n1+n2+1);        cin>>m;        for (int i=0; i<m; i++)        {            cin>>t1>>t2;            mp[t1].link_v.push_back(t2);   //邻接表无向边            mp[t2].link_v.push_back(t1);        }        cout<<Hungry()<<endl;    }fclose(stdin);fclose(stdout);return 0;}



后来找一道裸题,POJ1274试验了一下,稍微改动了一下输入格式,轻松AC了。

/*******************************************************************************//* OS           : 3.2.0-58-generic #88-Ubuntu SMP Tue Dec 3 UTC 2013 GNU/Linux * Compiler     : g++ (GCC)  4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) * Encoding     : UTF8 * Date         : 2014-04-06 * All Rights Reserved by yaolong.*****************************************************************************//* Description: ********************************************************************************************************************************************//* Analysis: ***********************************************************************************************************************************************//*****************************************************************************/#include <iostream>#include <cstring>#include<vector>#include<vector>#include<cstdio>using namespace std;#define N 500int n1,n2,m; //n1为A集合数,n2为B集合数,m为边数bool stat[N];int res[N];class Vertex{public:    Vertex(int n)    {        link_v.resize(n);    }    Vertex()    {        link_v.clear();    }    vector<int> link_v;};vector<Vertex> mp;bool find(int k){    vector<int> ::iterator itr=mp[k].link_v.begin();    vector<int> ::iterator itr_end=mp[k].link_v.end();    while(itr!=itr_end)    {        if(stat[*itr]==0)   //未标记=>不在增长路径        {            stat[*itr]=1;            if(res[*itr]==0   //未匹配点                    ||find(res[*itr]))   //还有增长路径            {                res[*itr]=k;    //标记*itr =k                return true;            }        }        itr++;    }    return false;}int Hungry(){    int ans=0;    memset(res,0,sizeof(res));    for(int i=1; i<=n1; i++)    {        memset(stat,0,sizeof(stat));        if(find(i)) ans++;    }    return ans;}int main(){    int t1,t2;    while(cin>>n1>>n2)    {        mp.clear();        mp.resize(n1+n2+1);        for(int j=1;j<=n1;j++){         cin>>m;        for (int i=0; i<m; i++)        {            cin>>t1;            mp[n1+t1].link_v.push_back(j);            mp[j].link_v.push_back(n1+t1);        }        }        cout<<Hungry()<<endl;    }return 0;}




0 0