【题目链接】
http://poj.org/problem?id=3281
题目意思
有F中食物,D种饮料,n头牛。每种牛吃不同种类的食物和饮料,每种食物
饮料只能一只牛吃,问最多满足多少头牛?
解题思路
把食物和饮料分两边,一头牛分成两个点放中间,容量为1.最后建立两个虚点
代码部分
include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <string>
#include <map>
using namespace std;
#define inf 0x3f3f3f3
#define LL long long
#define pii pair<int ,int>
const int N = 450;
int n,f,d,maxflow;
int mp[N][N];
int dis[N]; //
int cnt[N]; //0为源点, 2*n+f+d+1为汇点
bool ok;
void init() //初始化
{
memset(dis,0,sizeof(dis));
cnt[0] = 2*n+f+d+2; //设置源点流为无限大
int i = 1;
memset(mp,0,sizeof(mp));
for(; i <= f; i++) //源点到食物的权值为1
mp[0][i] = 1;
for (; i <= n+f; i++) //把牛拆成两点,之间的权值也为1
mp[i][i+n] = 1;
for (i = 1+2*n+f; i <= 2*n+d+f; i++) //饮料与汇点的权值为1
mp[i][2*n+d+f+1] = 1;
}
int Sap(int s,int mflow) //现在点的编号,最小的流
{
int midis;
if (s == 2*n+f+d+1)
{
ok = true;
maxflow += mflow;
return mflow;
}
midis = 2*n+f+d; //可流边的最小编号
for (int i = 0; i <= 2*n+f+d+1; i++)
{
if (mp[s][i] > 0)
{
if (dis[s] == dis[i]+1)
{
int flow = Sap(i,min(mflow,mp[s][i]));
if (ok){
mp[s][i] -= flow;
mp[i][s] += flow;
return flow;
}
}
midis = min(midis,dis[i]);
}
}
//GAP优化
cnt[dis[s]]--;
if (cnt[dis[s]] == 0) dis[0] = 2*n+f+d+1;
dis[s] = midis + 1;
cnt[dis[s]]++;
}
int main()
{
while (~scanf("%d %d %d",&n,&f,&d))
{
init();
int ff,dd,vf,vd;
for (int i = 1; i <= n; i++)
{
scanf("%d %d",&ff,&dd);
for (int j = 0; j < ff; j++)
{
scanf("%d",&vf);
mp[vf][i+f] = 1; //食物与牛1
}
for (int j = 0; j < dd; j++)
{
scanf("%d",&vd);
mp[i+n+f][2*n+f+vd] = 1; //饮料与牛2
}
}
maxflow = 0;
while (dis[0] < 2*n+f+d+1)
{
ok = false;
Sap(0,inf);
}
printf("%d\n",maxflow);
}
return 0;
}