匈牙利算法(最大匹配问题):

转自https://blog.csdn.net/sixdaycoder/article/details/47680831
匈牙利算法:
二分图的最大匹配可以转换为一个网络流的问题,但是我们一般使用匈牙利算法,这种算法更易于理解,方便编写。
介绍这个算法之前,首先要介绍一些必要的概念。

交错路 : 从一个未匹配点出发,依次遍历未匹配边、匹配边、未匹配边,这样交替下去,这条路径称为交错路。

增广路 : 从一个未匹配点出发,依次遍历未匹配边、匹配边、未匹配边,这样交替下去,如果最后一个点是未匹配点,这条路径称为增广路。换句话说,起点和终点都为未匹配点的交错路为增广路(特别提醒,这里的增广路和网络流中的增广路的意义不同)

并且给出hdu 2063当做模板 :

代码:
**#include<iostream>
**#include<cstring>
**#include<cstdio>******
using namespace std;
const int maxn = 505;
const int maxm = 1005;
struct Edge
{
    int to,next;
};
Edge edge[maxn];
int head[maxn],tot;
int match[maxn],ans;//match[x] = y表示x的匹配是y
bool inCrossPath[maxn];//在交错路中
int k,m,n;

void Init()
{
    memset(match,-1,sizeof(match));
    memset(head,-1,sizeof(head));
    tot = 0;
    ans = 0;
}
void addEdge(int u,int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
bool findpath(int u)
{
    int v;

    for(int i = head[u] ; i != -1 ; i = edge[i].next){
        v = edge[i].to;
        if(inCrossPath[v] == false){
            inCrossPath[v] = true;
            if(match[v] == -1 || findpath(match[v])){
                match[v] = u;
                return true;
            }
        }
    }
    return false;//千万别忘了这句
}
void Hungary()
{
    for(int i = 1 ; i <= m ; ++i){//只有女生有选择的权利,女生相当于X集合
        memset(inCrossPath,false,sizeof(inCrossPath));//每次清空交错路径
        if(findpath(i))
            ans++;
    }
}
int main()
{
    int u,v;
    while(scanf("%d",&k) != EOF && k){
        Init();
        scanf("%d%d",&m,&n);
        for(int i = 1 ; i <= k ; ++i){
            scanf("%d%d",&u,&v);
            addEdge(u,v);
        }
        Hungary();
        printf("%d\n",ans);
    }
    return 0;
}
另一种代码:
**#include<stdio.h>
**#include<string.h>
**#include<ctype.h>******
int n,m;
bool line[550][550];
int vis[550],boy[550];
bool find(int x)
{
    int i,j;
    for(j=1;j<=n;j++){      //扫描每一个boy 
        if(!vis[j]&&line[x][j]){    //如果这个boy没有找过,且girl x愿意跟这个boy做partner; 
            vis[j]=1;               //标记这个boy,防止递归的时候重复; 
            if(boy[j]==0||find(boy[j])){    //如果这个boy现在没有girl跟他做partner,或者能够腾出来找到其他的girl 
                boy[j]=x;
                return true;
            }
        }
    }
    return false;
}
int main ()
{
    int i,k,sum,a,b;
    while(~scanf("%d",&k)){
        if(k==0)
            break;
        scanf("%d %d",&m,&n);
        memset(line,0,sizeof(line));
        while(k--){
            scanf("%d %d",&a,&b);
            line[a][b]=1;
        }
        memset(boy,0,sizeof(boy));
        sum=0;
        for(i=1;i<=m;i++){              //扫描每一个girl ; 
            memset(vis,0,sizeof(vis));
            if(find(i))                 //如果这个girl可以找到他的partner,则sum++; 
                sum++;
        }
        printf("%d\n",sum);
    }
    return 0;
}

强烈推荐,易懂,你值得拥有

猜你喜欢

转载自blog.csdn.net/qq_41995906/article/details/81232091
今日推荐