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