无权二分图最大匹配 HDU2063 匈牙利算法 || Hopcroft-Karp

参考两篇比较好的博客 

http://www.renfei.org/blog/bipartite-matching.html

http://blog.csdn.net/thundermrbird/article/details/52231639###;

最大匹配数为n     2*n个不同的点    n条不同的边

匈牙利算法

从未匹配的的点出发寻找   非匹配边大于匹配边的交替路(增广路)匹配边与非匹配边交换

匈牙利算法模板(DFS,邻接矩阵版) 时间复杂度O(V*E)

 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <string.h>
 4 #include <stdlib.h>
 5 #include <iostream>
 6 #include <sstream>
 7 #include <algorithm>
 8 #include <string>
 9 #include <queue>
10 #include <map>
11 #include <vector>
12 using namespace std;
13 const int maxn = 1005;
14 const int maxm = 1e4+10;
15 const int inf = 0x3f3f3f3f;
16 const double epx = 1e-10;
17 typedef long long ll;
18 int n,m,k;
19 int visit[maxn];
20 int match[maxn];
21 int a[maxn][maxn];
22 bool found(int x)
23 {
24     for(int i=1;i<=m;i++)            //从右边的集合中找能与x进行匹配的点
25     {
26         if(a[x][i]==1&&visit[i]==0)   //x与i有联系且i没被查找过
27         {
28             visit[i]=1;
29             if(match[i]==0||found(match[i]))  //第i个点还没有匹配 如果匹配了就看 与它匹配的那个点 能不能换个点完成匹配 把i空出来 如果可以i与x匹配
30             {
31                 match[i]=x;
32                 return true;
33             }
34         }
35     }
36     return false;
37 }
38 int main()
39 {
40     while(scanf("%d",&k)!=EOF&&k)  //k条边
41     {
42         scanf("%d%d",&n,&m);      //左右两个集合的数量
43         memset(a,0,sizeof(a));
44         for(int i=1;i<=k;i++)
45         {
46             int x,y;
47             scanf("%d %d",&x,&y);
48             a[x][y]=1;               //有联系的点标记为1
49         }
50         memset(match,0,sizeof(match)); 
51         int ans=0;
52         for(int i=1;i<=n;i++)               //依次对左边集合中点进行匹配
53         {
54             memset(visit,0,sizeof(visit));  //清空访问标记数组 
55             if(found(i))             //满足条件匹配数+1
56                 ans++;
57         }
58         printf("%d\n",ans);
59     }
60 }

 

Hopcroft-Karp 算法

复杂度 O(sqrt(n)*E)

邻接表存图,vector 实现 ,vector 先初始化,然后加入边 , uN 为左端的顶点数,使用前赋值 (点编号 0 开始) 

#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("\n")
#define debug(a,b) cout<<a<<" "<<b<<" "<<endl
#define ffread(a) fastIO::read(a)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 1000+5;
const int INF = 0x3f3f3f3f;
vector<int>G[MAXN];
int uN;
int Mx[MAXN],My[MAXN];
int dx[MAXN],dy[MAXN];
int dis;
bool used[MAXN];
void init(int n)
{
    uN=n;
    for(int i=0; i<n; i++)
        G[i].clear();
}
bool SearchP()
{
    queue<int>Q;
    dis = INF;
    memset(dx,-1,sizeof(dx));
    memset(dy,-1,sizeof(dy));
    for(int i = 0 ; i < uN; 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;
        int sz = G[u].size();
        for(int i = 0; i < sz; i++)
        {
            int v = G[u][i];
            if(dy[v]==-1)
            {
                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)
{
    int sz = G[u].size();
    for(int i = 0; i < sz; i++)
    {
        int v = G[u][i];
        if(!used[v] && dy[v] == dx[u] + 1)
        {
            used[v] = true;
            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(used,false,sizeof(used));
        for(int i = 0; i < uN; i++)
            if(Mx[i] == -1 && DFS(i))
                res++;
    }
    return res;
}
int main()
{
    int n,m,k;
    while(scanf("%d",&k)&&k)
    {
        scanf("%d%d",&m,&n);
        init(m);
        for(int i=0; i<k; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            G[x-1].pb(y-1);
        }
        printf("%d\n",MaxMatch());
    }
}

 

posted @ 2018-01-22 20:20  灬从此以后灬  阅读(184)  评论(0编辑  收藏  举报