POJ 1469二分图匹配Hopcroft-Karp算法

题意:

有N个学生和P门课程,让你判断能否构成最大匹配。先输入一个T,表示有T组测试数据;在输入N和P,P表示有P门课程,N表示有N个学生。之后有P行,比如:

a  a1 a2 a3 a4 a5---第一行。1与a1,a2,a3,a4,a5有匹配。

b b1 b2 b3-----第二行。2与b1,b2,b3有匹配。

如果匹配数等于学生数目则YES;否则为NO;

上交模板,因为用了bfs增广一系列路径,所以更快……

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define sc(a,b) scanf("%d%d",&a,&b)
#define pri(a) printf("%d\n",a)
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define MM 50005
#define MN 500
#define INF 0x7fffffff
#define eps 1e-7
using namespace std;
typedef long long ll;
int nx,ny,vis[MM],mx[MM],my[MM],dx[MM],dy[MM];
vector<int>e[MM];
queue<int>q;
bool dfs(int u)
{
    int i,l=e[u].size();
    for(i=0;i<l;i++)
    {
        int v=e[u][i];
        if(!vis[v]&&dy[v]==dx[u]+1)
        {
            vis[v]=1;
            if(!my[v]||dfs(my[v]))
            {
                mx[u]=v;
                my[v]=u;
                return true;
            }
        }
    }
    return false;
}
int HK()  //Hopcroft_Karp算法
{
    mem(mx,0); mem(my,0);
    int ans=0;
    while(1)
    {
        int flag=0,i;
        while(!q.empty()) q.pop();
        mem(dx,0); mem(dy,0);
        for(i=1;i<=nx;i++) if(!mx[i]) q.push(i);
        while(!q.empty())
        {
            int u=q.front(),l=e[u].size(); q.pop();
            for(i=0;i<l;i++)
            {
                int v=e[u][i];
                if(!dy[v])
                {
                    dy[v]=dx[u]+1;
                    if(my[v])
                    {
                        dx[my[v]]=dy[v]+1;
                        q.push(my[v]);
                    }
                    else flag=1;
                }
            }
        }
        if(!flag) break;
        mem(vis,0);
        for(i=1;i<=nx;i++)
            if(!mx[i]&&dfs(i)) ans++;
    }
    return ans;
}
int main()
{
    int t;
    sca(t);
    while(t--)
    {
        int u,v,i,a;
        sc(nx,ny);
        for(i=0;i<=nx;i++) e[i].clear();
        for(u=1;u<=nx;u++)
        {
            sca(a);
            for(i=0;i<a;i++)
                sca(v),e[u].push_back(v);
        }
        puts(HK()==nx?"YES":"NO");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值