现在的位置: 首页 > 综合 > 正文

hdu 2063(二分图匹配匈牙利)

2018年04月26日 ⁄ 综合 ⁄ 共 2315字 ⁄ 字号 评论关闭
#include<stdio.h>
#include<string.h>
const int max=510;
int map[max][max];
int flag[max],mat[max],k,n,m;
int find(int i)
{
	for(int j=1;j<=m;j++)
		if(!flag[j]&&map[i][j])
		{
			flag[j]=1;
	       if(mat[j]==-1||find(mat[j]))
		   {
			   mat[j]=i;
		       return 1;
		   }
		}
		return 0;
}
int matchpeople(int n,int m)
{
	int match=0;
	memset(mat,-1,sizeof(mat));
	for(int i=1;i<=n;i++)
	{
		memset(flag,0,sizeof(flag));
		match+=find(i);
	}
	return match;
}
int main()
{
	int i,girl,boy;
	while(scanf("%d",&k)&&k)
	{
		scanf("%d%d",&n,&m);
		memset(map,0,sizeof(map));
		for(i=0;i<k;i++)
		{
			scanf("%d%d",&girl,&boy);
			map[girl][boy]=1;
		}
		printf("%d\n",matchpeople(n,m));
	}
	return 0;
}

邻接表的形式:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
 
const int NV = 1005;
const int NE = 3000;
 
struct MaxMatch {
    int n, size;
    int head[NV];
    int aug[NV];
    bool mark[NV];
 
    struct Edge {
        int v, w, next;
        Edge () {}
        Edge (int V, int NEXT, int W = 0) : v(V), next(NEXT), w(W) {}
    }E[NE];
 
    inline void init(int vx) {
        n = vx, size = 0;
        for (int i = 0; i <= n; i++) {
            head[i] = -1;
        }
    }
 
    inline void insert(int u, int v, int w = 0) {
        E[size] = Edge(v, head[u], w);
        head[u] = size++;
    }
 
    inline int Hungary(int n) {
        int match = 0;
        memset(aug, -1, sizeof(aug));
        for (int i = 1; i <= n; i++) {
            if (aug[i] == -1) {//剪枝
                memset(mark, false, sizeof(mark));
                match += Find(i);
            }
        }
        return match;
    }//Hungray
 
    inline bool Find(int u) {
        for (int i = head[u]; i != -1; i = E[i].next) {
            int v = E[i].v;
            if (mark[v]) continue;
            mark[v] = true;
            if (aug[v] == -1 || Find(aug[v])) {
                aug[v] = u, aug[u] = v;
                return true;
            }
        }
        return false;
    }//Find
}G;
 
int main() {
       int k, m, n, a, b;
       while (~scanf("%d", &k), k) {
           scanf("%d%d", &m, &n);
           G.init(m + n);
           while (k--) {
               scanf("%d%d", &a, &b);
               G.insert(a, b + m);
         }//while(k--)
         printf("%d\n", G.Hungary(m));
      }//while
   return 0;
}

 

网上容易理解的详细描述:

#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;

const int N = 505;

bool map[N][N], flag[N];
int pre[N];
int n, m, num;

//匈牙利算法(二分匹配)
int find(int cur)   //cur为当前女生
{
    int i;
    for(i = 1; i <= m; i++) //被匹配的男生
    {
        if(map[cur][i] && !flag[i]) //该男生未被匹配
        {
            flag[i] = true; //这次匹配中,标记该男生已匹配
            if(pre[i] == -1 || find(pre[i]))    //该男生没有女生 or 该女生继续找其他男生 -> ok
            {
                pre[i] = cur;   //男生[i]属于女生cur
                return 1;
            }
        }
    }
    return 0;
}

int main()
{
    int i, girl, boy, sum;
    while(scanf("%d", &num), num)
    {
        scanf("%d %d", &n, &m);     //n是女生数量,m是男生数量
        memset(map, false, sizeof(map));
        memset(pre, -1, sizeof(pre));
        for(i = 0; i < num; i++)
        {
            scanf("%d %d", &girl, &boy);
            map[girl][boy] = true;  //可以匹配
        }
        sum = 0;
        for(i = 1; i <= n; i++)     //女生去匹配男生
        {
             memset(flag, 0, sizeof(flag)); //每次重新标记0
             sum += find(i);
        }
        printf("%d\n", sum);
    }

    return 0;
}

匈牙利二分匹配主要是增广路的查找,逐个逐个匹配,若那个人被匹配了,则找匹配那个的人看看能不能找其他人匹配,不断地找,

抱歉!评论已关闭.