poj1469 二分图最大匹配 匈牙利算法BFS实现

来源:互联网 发布:windows 启动管理器 编辑:程序博客网 时间:2024/05/16 23:41

                                                         POJ 1469

二分图讲解:点击打开链接

大致题意:

有n个学生和p门课程,每个人可以选0,1,2......门课程。给你每个学生喜欢的课程编号,然后问你是否能从n中选p个学生,使得每个学生所选的课程都不同且每门课程都有一个人选。

大致思路:

其实题意就是问你是否能找出p个1对1的关系。那么根据二分图最大匹配性质,我们只需找出最大匹配数,看是否和课程书相同,是的话,那就代表能成功。

直接套模板,我用的是BFS,据说BFS比DFS更稳定。

代码:

#include<stdio.h>#include<iostream>#include<queue>#include<vector>#include<string.h>using namespace std;int pre[305],vis[305];pre数组用来存储路径,等更改匹配边时要用到。int ml[305],mr[305];//左集合点的匹配点  右集合点的匹配点   int p,n;vector<int>V[30005];//vector存图int MaxMatch()//bfs实现匈牙利算法{    int ans=0;    memset(vis,0,sizeof(vis));    memset(ml,-1,sizeof(ml));    memset(mr,-1,sizeof(mr));    for(int i=1; i<=p; i++)    {        if(ml[i]!=-1)continue;        queue<int>Q;        Q.push(i);        pre[i]=-1;        int flag=0;//是否找到增广路        while(!Q.empty()&&!flag)        {            int v=Q.front();            Q.pop();            for(int j=0; j<V[v].size()&&!flag; j++)            {                int to=V[v][j];                if(vis[to]!=i)                {                    vis[to]=i;                    Q.push(mr[to]);                    if(mr[to]>=0)                    {                        pre[mr[to]]=v;//没找到增广路,记下路径                    }                    else//找到了                    {                        flag=1;                        int d=v;                        int e=to;                        while(d!=-1)//更改路径                        {                            int temp=ml[d];                            ml[d]=e;                            mr[e]=d;                            e=temp;                            d=pre[d];                        }                    }                }            }        }        if(flag)ans++;//找到增广路,匹配边加一条    }    return ans;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&p,&n);        int num,a;        for(int i=1; i<=p; i++)        {            V[i].clear();            scanf("%d",&num);            for(int j=1; j<=num; j++)            {                scanf("%d",&a);                V[i].push_back(a);            }        }        int ans=MaxMatch();        //printf("%d\n",ans);        if(ans==p)            printf("YES\n");        else            printf("NO\n");    }}

第一次做二分图类题,看了一下午,终于略有所懂,写一道简单题找找感觉~~~~~

阅读全文
0 0
原创粉丝点击