题意
XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化。由于很多来住店的旅客有自己喜好的房间色调、阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只有固定的q道不同的菜。
有一天来了n个客人,每个客人说出了自己喜欢哪些房间,喜欢哪道菜。但是很不幸,可能做不到让所有顾客满意(满意的条件是住进喜欢的房间,吃到喜欢的菜)。
这里要怎么分配,能使最多顾客满意呢?
\(n,p,q \leq 100\)
分析
将人拆成两个点,中间加一条容量为1的边。
然后源点连房间,房间连人,人连菜,菜连汇点,跑最大流就行了。
时间复杂度\(O(n^4)\)
代码
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<algorithm>
#include<string>
template<class T>T read(T&x)
{
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
{
data=data*10+ch-'0';
ch=getchar();
}
return x=data*w;
}
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=407,MAXM=5e4+7;
int n,p,q; // people,room,meal
struct edge
{
int nx,to,c;
}e[MAXM];
int head[MAXN],ecnt;
void addedge(int x,int y,int c)
{
e[++ecnt].to=y,e[ecnt].c=c;
e[ecnt].nx=head[x],head[x]=ecnt;
}
int dep[MAXN],cur[MAXN];
queue <int> Q;
bool bfs(int s,int t)
{
copy(head,head+t+1,cur);
fill(dep+s,dep+t+1,INF);
dep[s]=0;
Q.push(s);
while(Q.size())
{
int x=Q.front();
Q.pop();
for(int i=head[x];i!=-1;i=e[i].nx)
{
int y=e[i].to,c=e[i].c;
if(c>0&&dep[y]==INF)
{
dep[y]=dep[x]+1;
Q.push(y);
}
}
}
return dep[t]<INF;
}
int dfs(int x,int t,int lim)
{
if(x==t||!lim)
return lim;
int delta=0,inc;
for(int i=cur[x];i!=-1;i=e[i].nx)
{
cur[x]=i;
int y=e[i].to,c=e[i].c;
if(dep[y]==dep[x]+1&&(inc=dfs(y,t,min(lim,c))))
{
lim-=inc;
delta+=inc;
e[i].c-=inc;
e[i^1].c+=inc;
if(!lim)
break;
}
}
return delta;
}
int Dinic(int s,int t)
{
int res=0;
while(bfs(s,t))
res+=dfs(s,t,INF);
return res;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n);read(p);read(q);
fill(head,head+p+2*n+q+2,-1);
ecnt=-1;
for(int i=1;i<=p;++i)
{
addedge(0,i,1);
addedge(i,0,0);
}
for(int i=1;i<=n;++i)
for(int j=1;j<=p;++j)
{
int opt;
read(opt);
if(opt)
{
addedge(j,p+i,1);
addedge(p+i,j,0);
}
}
for(int i=1;i<=n;++i)
{
addedge(p+i,p+n+i,1);
addedge(p+n+i,p+i,0);
}
for(int i=1;i<=n;++i)
for(int j=1;j<=q;++j)
{
int opt;
read(opt);
if(opt)
{
addedge(p+n+i,p+2*n+j,1);
addedge(p+2*n+j,p+n+i,0);
}
}
for(int i=1;i<=q;++i)
{
addedge(p+2*n+i,p+2*n+q+1,1);
addedge(p+2*n+q+1,p+2*n+i,0);
}
int ans=Dinic(0,p+2*n+q+1);
printf("%d\n",ans);
return 0;
}