void-man

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

题目给出几个牛相应的生产机器,一个牛只能对应一个机器,一个机器只能对应一头牛。最多匹配多少头牛?

简单的最大匹配,匈牙利算法直接过,但是网络流也可以解决此类问题,把每个边的cap容量设置成1,把0节点设置成初始节点,并且和牛都有边

结尾点设置成m+n+1,和机器都有边,这样可构建一个网络流的图

如图,把此问题建图,然后用EK网络流算法得出

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string.h>
#include <queue>
#include <limits.h>
#define MAX 420
using namespace std;
int n,m;
int cap[MAX][MAX];
int EKarp(int s,int t)
{
	queue<int> Q;
	int flow[MAX][MAX],pre[MAX],a[MAX];
	int u,v,to,f = 0;
	memset(flow,0,sizeof(flow));
	while(1)
	{
		memset(a,0,sizeof(a));
		a[s] = INT_MAX;
		Q.push(s);
		while( !Q.empty() )
		{
			u = Q.front();
			Q.pop();
			for(v=s; v<=t; v++)
				if( !a[v] && cap[u][v] > flow[u][v] )
				{
					Q.push(v);
					pre[v] = u;
					a[v] = a[u] < cap[u][v] - flow[u][v] ? a[u] : cap[u][v] - flow[u][v];
				}
		}
		if( a[t] == 0 )
			break;
		for(u=t; u!=s; u=pre[u])
		{
			flow[pre[u]][u] += a[t];
			flow[u][pre[u]] -= a[t];
		}
		f += a[t];
	}
	return f;
}
int main()
{
	int i,ans,to,num;
	while( scanf("%d%d",&n,&m) != EOF )
	{
		memset(cap,0,sizeof(cap));
		for(i=1; i<=n; i++)
		{
			scanf("%d",&num);
			while( num-- )
			{
				scanf("%d",&to);
				cap[m+i][to] = 1;
			}
		}
		for(i=m+1; i<=m+n; i++)
			cap[0][i] = 1;
		for(i=1; i<=m; i++)
			cap[i][m+n+1] = 1;
		ans = EKarp(0,m+n+1);
		printf("%d\n",ans);	
	}
return 0;
}

匈牙利算法,求二分匹配直接套模版

#include <stdio.h>
#include <string.h>
#define N 201
int match[N],map[N][N];
int cn,mn;
bool used[N];
int find(int x)
{
    for(int i=1;i<=mn;i++)
    if(!used[i]&&map[x][i])
    {
        used[i]=true;
        if(match[i]==-1||find(match[i]))
        {
            match[i]=x;
            return true;
        }
        
    }
    return false;
}

int Hungry()
{
    int sum=0;
    for(int i=1;i<=cn;i++)
    {
        memset(used,false,sizeof(used));
        if(find(i))sum++;
    }
    return sum; 
}

int main()
{
    int num,st;
    while(~scanf("%d%d",&cn,&mn))
    {
        memset(map,0,sizeof(map));
        memset(match,-1,sizeof(match));
        for(int i=1;i<=cn;i++)
        {
            scanf("%d",&num);
            while(num--)
            {
                scanf("%d",&st);
                map[i][st]=1;
            }
            
        }
        printf("%d\n",Hungry());
        
    }
    
}
posted on 2011-05-16 13:37  void-man  阅读(328)  评论(0)    收藏  举报