题目给出几个牛相应的生产机器,一个牛只能对应一个机器,一个机器只能对应一头牛。最多匹配多少头牛?
简单的最大匹配,匈牙利算法直接过,但是网络流也可以解决此类问题,把每个边的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());
}
}

浙公网安备 33010602011771号