zoukankan      html  css  js  c++  java
  • dfs,bfs的二分匹配模板(模板题hdu1150)

    如果不懂匈牙利算法,请点击:该趣味算法http://blog.csdn.net/dark_scope/article/details/8880547

    模板:
    //DFS版本下的二分匹配算法
    http://paste.ubuntu.net/16122581/

    #include<cstdio>
    #include<iostream>
    #include<vector>
    #include<set>
    #include<map>
    #include<math.h>
    #include<queue>
    #include<stdlib.h>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    
    //DFS版本下的二分匹配算法
    
    const int MAXN = 300;       //最大顶点数
    bool bmap[MAXN][MAXN];      //二分图
    bool bmask[MAXN];     //寻找增广路径的标志数组
    int nx,ny;                  //nx为左顶点的个个数,ny为右顶点的个数
    int cx[MAXN];               //cx[i]表示左集合i顶点所匹配到的右集合的顶点的序号。
    int cy[MAXN];               //cy[i]表示右集合i顶点所匹配到的左集合的顶点的序号。
    int k;
    
    int findpath(int u)
    {
        int i;
        for(i=0;i<ny;i++)   //扫描每个妹子
        {
            //如果【有暧昧】并且【还没有标记过】
            //这里标记的意思是这次查找【曾】试图改变过该妹子的归属问题
            //但是没有成功,所以就不用瞎费工夫了
            if(bmap[u][i]&&!bmask[i])
            {
                bmask[i]=1;
                if(cy[i]==-1||findpath(cy[i]))   //名花无主 或者 能腾出个位置来,这里使用递归
                {
                    cy[i]=u;
                    cx[u]=i;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int MaxMatch()
    {
        int res=0;                     //有多少对
        int i,j;
        for(int i=0;i<nx;i++)
            cx[i]=-1;
        for(int i=0;i<ny;i++)
            cy[i]=-1;
        for(int i=0;i<nx;i++)           //为男生找配偶
        {
            if(cx[i]==-1)
            {
                for(int j=0;j<ny;j++)   //这个在每一步中清空
                    bmask[j]=0;
                res+=findpath(i);
            }
        }
        return res;
    }
    
    int main()
    {
        while(~scanf("%d",&nx)&&nx)
        {
            scanf("%d%d",&ny,&k);
            int x;
            memset(bmap,0,sizeof(bmap));
            int a,b;
            for(int i=0;i<k;i++)
            {
                scanf("%d%d%d",&x,&a,&b);
                if(a>0&&b>0)
                    bmap[a][b]=1;
            }
            int ans=MaxMatch();
            printf("%d
    ",ans);
        }
        return 0;
    }
    /*
    
    2 2 3
    0 1 1
    1 2 1
    2 2 2
    
    
    */

    //BFS版本下的二分匹配算法
    http://paste.ubuntu.net/16122732/

    #include<cstdio>
    #include<string.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    
    //BFS版本下的二分匹配算法
    
    //我觉得DFS的很好理解,所以我觉得套用DFS的讲,可能有偏差;
    
    const int MAXN = 1000;      //最大顶点数
    int bmap[MAXN][MAXN];        //二分图
    int cx[MAXN];             //cx[i]表示左集合i顶点所匹配到的右集合的顶点的序号。
    int cy[MAXN];            //cy[i]表示右集合i顶点所匹配到的左集合的顶点的序号。
    int nx,ny,k;              //nx为左顶点的个个数,ny为右顶点的个数
    
    int bmask[MAXN];        //寻找增广路径的标志数组
    int que[MAXN];          //队列保存扩展顶点
    int pre[MAXN];          //记录前置顶点
    
    int MaxMatch()
    {
        int res=0;
        int qs,qe;
        memset(cx,-1,sizeof(cx));
        memset(cy,-1,sizeof(cy));
        memset(bmask,-1,sizeof(bmask));
    
        for(int i=0;i<nx;i++)
        {
            if(cx[i]==-1)           //为男的寻找配偶
            {
                qs=qe=0;            //队列初始化
                que[qe++]=i;        
                pre[i]=-1;
                bool flag=0;
                while(qs<qe&&!flag)
                {
                    int u=que[qs];
                    for(int v=0;v<ny&&!flag;v++)
                    {
                        if(bmap[u][v]&&bmask[v]!=i) //如果有关系,但是这个关系并不是给我们要配对的男生
                        {
                            bmask[v]=i;             //但是...该男子强行拿过来作为妻子
                            que[qe++]=cy[v];        //所以女生本来的丈夫就很伤了
                            if(cy[v]>=0)            //如果那个人有丈夫的话,就用pre记录前置节点
                            {
                                pre[cy[v]]=u;
                            }
                            else                    //但是该女子没有丈夫,那就是刚刚好
                            {
                                flag=1;             //OK解决问题
                                int d=u,e=v;
                                while(d!=-1)        //然后这就是类似于DFS算法中的回溯,这建立了改男子配对下的状态是什么样子的。
                                {
                                    int t=cx[d];
                                    cx[d]=e;cy[e]=d;
                                    d=pre[d];e=t;
                                }
                            }
                        }
                    }
                    qs++;
                }
                if(cx[i]!=-1)       //有多少配对的男子,就加几个
                {
                    res++;
                }
            }
        }
        return res;
    }
    
    int main()
    {
        while(~scanf("%d",&nx)&&nx)
        {
            scanf("%d%d",&ny,&k);
            int x;
            memset(bmap,0,sizeof(bmap));
            int a,b;
            for(int i=0;i<k;i++)
            {
                scanf("%d%d%d",&x,&a,&b);
                if(a>0&&b>0)
                    bmap[a][b]=1;
            }
            int ans=MaxMatch();
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Vue生态圈之----vue-router----路由配置
    Vue生态圈之----vue-router----基础实例
    Webpack学习整理之----最简单的实例
    Webpack学习整理之----配置
    Webpack学习整理之----概念
    多个系统域名使用同一认证中心做单点登录的做法
    JavaScript基础概念之----Commonjs、CMD、AMD、UMD
    npm 镜像及使用
    nvm 指令
    mongodb安装配置启动踩的坑
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/5934558.html
Copyright © 2011-2022 走看看