zoukankan      html  css  js  c++  java
  • 二分图最大匹配

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

    匈牙利算法写起来还是很简单的,基本上理解了交错路之后就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 500
    int 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 500
    int 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;
    
    }
    
    
    




  • 相关阅读:
    插入排序
    JavaMail学习笔记
    汉诺塔问题
    使用Three.js绘制一个虚拟城市
    jquery flotcharts使用简介
    用CSS hack技术解决浏览器兼容性问题.
    IE条件注释详解.
    让IE6也认识!important
    代码重构(转)
    模版+数据分离渲染方式的设计与实现
  • 原文地址:https://www.cnblogs.com/dengyaolong/p/3697205.html
Copyright © 2011-2022 走看看