POJ 3281 Dining | 最大流
将牛拆为两个点.
原点向食物连边,食物向牛1连边,牛1向牛2连边,牛2向饮料连边,跑最大流即可
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define MAXN 1010
#define INF 1000000
using namespace std;
int N,F,D,ecnt=1,k1,k2,S,T,x,tmp,lev[MAXN],ans,head[MAXN];
queue <int> q;
struct adj
{
int u,v,w;
}e[10*MAXN];
void add(int u,int v,int w)
{
e[++ecnt].v=v;
e[ecnt].w=w;
e[ecnt].u=head[u];
head[u]=ecnt;
}
int bfs()
{
memset(lev,-1,sizeof(lev));
lev[S]=0;
q.push(S);
while (!q.empty())
{
int x=q.front();
for (int i=head[x];i;i=e[i].u)
{
int v=e[i].v;
if (lev[v]==-1 && e[i].w>0)
lev[v]=lev[x]+1,q.push(v);
}
q.pop();
}
return lev[T]!=-1;
}
int dfs(int x,int flw)
{
if (x==T) return flw;
for (int i=head[x];i;i=e[i].u)
{
int v=e[i].v,tmp;
if (lev[v]==lev[x]+1 && e[i].w>0 && (tmp=dfs(v,min(flw,e[i].w)))>0)
{
e[i].w-=tmp;
e[i^1].w+=tmp;
return tmp;
}
}
return 0;
}
int main()
{
scanf("%d%d%d",&N,&F,&D);
S=F+D+2*N+1,T=F+D+2*N+2;
for (int i=1;i<=N;i++)
add(i,N+i,1),add(i+N,i,0);
for (int i=1;i<=N;i++)
{
scanf("%d%d",&k1,&k2);
while (k1--)
scanf("%d",&x),add(x+2*N,i,1),add(i,x+2*N,0);
while (k2--)
scanf("%d",&x),add(i+N,2*N+F+x,1),add(2*N+F+x,i+N,0);
}
// printf("READ OVER\n");
for (int i=1;i<=F;i++)
add(S,i+2*N,1),add(i+2*N,S,0);
for (int i=1;i<=D;i++)
add(2*N+F+i,T,1),add(T,2*N+F+i,0);
while (bfs())
while ((tmp=dfs(S,INF))>0) ans+=tmp;
printf("%d",ans);
return 0;
}

浙公网安备 33010602011771号