题目:
题解:
就是一个网络流(一开始搜二分图匹配的orz)
建图就是S->Room->P->P->Dish->T
容量都是1,人拆点是因为一个人只能使用一次
以后还要考虑的周密一些
代码:
#include <cstdio>
#include <queue>
#include <iostream>
#include <cstring>
#define N 105
#define INF 1e9+7
using namespace std;
int tot=-1,nxt[N*N*2],point[N*N*2],v[N*N*2],remind[N*N*2];
int cur[N*N*2],deep[N*N*2],s,t,n,p,q;
bool c[N][N+N];
void addline(int x,int y,int z)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; remind[tot]=z;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; remind[tot]=0;
}
int dfs(int now,int t,int limit)
{
int flow=0,f;
if (now==t || !limit) return limit;
for (int i=cur[now];i!=-1;i=nxt[i])
{
cur[now]=i;
if (deep[v[i]]==deep[now]+1 && (f=dfs(v[i],t,min(limit,remind[i]))))
{
flow+=f;
limit-=f;
remind[i]-=f;
remind[i^1]+=f;
if (!limit) break;
}
}
return flow;
}
bool bfs(int s,int t)
{
queue <int> q;
for (int i=s;i<=t;i++) cur[i]=point[i];
q.push(s);
memset(deep,0x7f,sizeof(deep));
deep[s]=0;
while (!q.empty())
{
int now=q.front(); q.pop();
for(int i=point[now];i!=-1;i=nxt[i])
if (deep[v[i]]>INF && remind[i])
{
deep[v[i]]=deep[now]+1;
q.push(v[i]);
}
}
if(deep[t]>INF) return false;
return true;
}
void dinic(int s,int t)
{
int ans=0;
while (bfs(s,t))
ans+=dfs(s,t,INF);
printf("%d",ans);
}
int main()
{
int i,j,k;
int a;
memset(nxt,-1,sizeof(nxt));
memset(point,-1,sizeof(point));
scanf("%d%d%d",&n,&p,&q);
s=0;t=p+q+1+2*n;
for (i=1;i<=p;i++)
addline(s,i,1);
for (i=1;i<=q;i++)
addline(i+p+n*2,t,1);
for (i=1;i<=n;i++)
for (j=1;j<=p;j++)
{
scanf("%d",&a);
if (a) addline(j,p+i,1);
}
for (i=1;i<=n;i++)
for (j=1;j<=q;j++)
{
scanf("%d",&a);
if (a) addline(p+i+n,p+n*2+j,1);
}
for (i=1;i<=n;i++)
addline(i+p,i+p+n,1);
dinic(s,t);
}