SPOJ Fast Maximum Matching(二分图最大匹配Hopcroft-Carp)

来源:互联网 发布:全志科技 知乎 编辑:程序博客网 时间:2024/06/05 11:15

题目大意:

有n1头公牛和n2头母牛,给出公母之间的m对配对关系,求最大匹配数。

数据范围:  1 <= n1, n2 <= 50000, m <= 150000

注意:该模板存边使用的是前向星,且二部图左右两边的点集编号均从1开始

#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<queue>using namespace std;const int maxn = 5e4+5;const int maxe = 15e4+5;//最大关系数const int INF = 1<<28;int tol, head[maxn];int Mx[maxn], My[maxn], Nx, Ny;//Nx左边点集合的个数,标号从1开始//Ny左边点集合的个数,标号从1开始int dx[maxn], dy[maxn], dis;bool vst[maxn*2];struct Edge{    int from, to, nxt;}edge[maxe];void init(){    tol = 0;    memset(head, -1, sizeof(head));}void addedge(int u, int v){    edge[tol].from = u;    edge[tol].to = v;    edge[tol].nxt = head[u];    head[u] = tol++;}bool searchP(){    queue<int> Q;    dis = INF;    memset(dx, -1, sizeof(dx));    memset(dy, -1, sizeof(dy));    for(int i = 1; i <= Nx; i++)        if(Mx[i] == -1)        {            Q.push(i);            dx[i] = 0;        }    while(!Q.empty())    {        int u = Q.front();        Q.pop();        if(dx[u] > dis) break;        for(int i = head[u]; i != -1; i = edge[i].nxt)        {            int v = edge[i].to;            if(dy[v] != -1) continue;            dy[v] = dx[u] + 1;            if(My[v] == -1)                dis = dy[v];            else            {                dx[My[v]] = dy[v]+1;                Q.push(My[v]);            }        }    }    return dis!=INF;}bool DFS(int u){    for(int i = head[u]; i != -1; i = edge[i].nxt)    {        int v = edge[i].to;        if(!vst[v] && dy[v] == dx[u]+1)        {            vst[v]=1;            if(My[v]!=-1&&dy[v]==dis) continue;            if(My[v]==-1||DFS(My[v]))            {                My[v]=u;                Mx[u]=v;                return true;            }        }    }    return false;}int MaxMatch(){    int res = 0;    memset(Mx, -1, sizeof(Mx));    memset(My, -1, sizeof(My));    while(searchP())    {        memset(vst, false, sizeof(vst));        for(int i = 1; i <= Nx; i++)            if(Mx[i] == -1 && DFS(i))                res++;    }    return res;}int main(){    int n, m, tol_edge, u, v;    //n左边点的数量,m右边点的数量,tol_edge关系数    while(scanf("%d%d%d", &n, &m, &tol_edge) != EOF)    {        init();        for(int i = 0; i < tol_edge; i++)        {            scanf("%d%d", &u, &v);            addedge(u, v);        }        Nx = n;Ny = m;        printf("%d\n", MaxMatch());    }    return 0;}


阅读全文
0 0