dfs,bfs的二分匹配模板(模板题hdu1150)

来源:互联网 发布:java ant下载 编辑:程序博客网 时间:2024/06/03 17:18

如果不懂匈牙利算法,请点击:该趣味算法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\n",ans);    }    return 0;}/*2 2 30 1 11 2 12 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\n",ans);    }    return 0;}
0 0
原创粉丝点击