poj 3281(最大流)
题目大意就是有n头牛,f种食物,d种饮料,每头牛都有其喜欢的食物和饮料,然后每一种食物和每一种饮料只能分配给一头牛,然后如果一头牛得到了它喜欢的食物和饮料的话,该牛就得到满足,问最多可以满足多少头牛。
这题建图非常的巧妙,最大流建图就是把食物和饮料放在两边,一头牛拆成牛左和牛右,每头牛的牛左和牛右的容量为1。每头牛喜欢的食物和该牛的牛左连边,容量为1,每头牛喜欢的饮料和该牛连边,容量为1,然后设一个源点,源点和全部食物连边,容量为1,最后设一个汇点,所以饮料和汇点连边,容量为1.这样图就建好了,跑个网络流最大流即可,我之前用的ek算法的板子在交这题时T了,所以换了个kuangbin的bfs实现的ek算法。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
int mp[505][505],flow[505],path[505];
int n,f,d,maxflow,st,et;
void init()
{
memset(mp,0,sizeof(mp));
maxflow=0;
}
bool bfs()
{
int i,t;
queue<int>q;
while(!q.empty()) q.pop();
memset(path,-1,sizeof(path));
path[st]=0;
flow[st]=inf;
q.push(st);
while(!q.empty())
{
t=q.front();
q.pop();
if(t==et) break;
for(int i=st;i<=et;i++)
{
if(i!=st&&path[i]==-1&&mp[t][i])
{
flow[i]=min(flow[t],mp[t][i]);
q.push(i);
path[i]=t;
}
}
}
if(path[et]==-1)
return false;
return true;
}
void ek()
{
while(bfs())
{
maxflow+=flow[et];
int now=et,pre;
while(now!=st)
{
pre=path[now];
mp[pre][now]-=flow[et];
mp[now][pre]+=flow[et];
now=pre;
}
}
}
int main()
{
scanf("%d%d%d",&n,&f,&d);
init();
st=0;
et=f+d+2*n+1;
for(int i=1;i<=f;i++)
mp[st][i]=1;
for(int i=f+2*n+1;i<=f+2*n+d;i++)
mp[i][et]=1;
for(int i=1;i<=n;i++)
mp[f+2*i-1][f+2*i]=1;
int k1,k2;
int u;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&k1,&k2);
while(k1--)
{
scanf("%d",&u);
mp[u][f+2*i-1]=1;
}
while(k2--)
{
scanf("%d",&u);
mp[f+2*i][f+2*n+u]=1;
}
}
ek();
printf("%d\n",maxflow);
return 0;
}