酒店之王
题目描述
XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化。由于很多来住店的旅客有自己喜好的房间色调、阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只有固定的q道不同的菜。
有一天来了n个客人,每个客人说出了自己喜欢哪些房间,喜欢哪道菜。但是很不幸,可能做不到让所有顾客满意(满意的条件是住进喜欢的房间,吃到喜欢的菜)。
这里要怎么分配,能使最多顾客满意呢?
输入输出格式
输入格式:
第一行给出三个正整数表示n,p,q(<=100)。
之后n行,每行p个数包含0或1,第i个数表示喜不喜欢第i个房间(1表示喜欢,0表示不喜欢)。
之后n行,每行q个数,表示喜不喜欢第i道菜。
输出格式:
最大的顾客满意数。
输入输出样例
输入样例#1:
2 2 2 1 0 1 0 1 1 1 1
输出样例#1:
1
题解:
裸的最大流,只不过人要拆成两个点,用以保证每一个人只用一次。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<queue> #include<stack> #include<vector> #include<ctime> using namespace std; int n,m,l; struct node { int next,to,cap; }edge[300001]; int size=1,head[501]; void putin(int from,int to,int cap) { size++; edge[size].next=head[from]; edge[size].cap=cap; edge[size].to=to; head[from]=size; } void in(int from,int to,int cap) { putin(from,to,cap); putin(to,from,0); } int dist[501],numbs[501]; void bfs(int src,int des) { int i; queue<int>mem; mem.push(des); numbs[0]++; while(!mem.empty()) { int x=mem.front();mem.pop(); for(i=head[x];i!=-1;i=edge[i].next) { int y=edge[i].to; if(edge[i].cap==0&&dist[y]==0&&y!=des) { dist[y]=dist[x]+1; numbs[dist[y]]++; mem.push(y); } } } return; } int dfs(int src,int flow,int des) { if(src==des)return flow; int i,low=0,mindist=n+n+m+l+2; for(i=head[src];i!=-1;i=edge[i].next) { int y=edge[i].to; if(edge[i].cap) { if(dist[y]==dist[src]-1) { int t=dfs(y,min(flow-low,edge[i].cap),des); edge[i].cap-=t; edge[i^1].cap+=t; low+=t; if(dist[src]>=n+n+m+l+2)return low; if(low==flow)break; } mindist=min(mindist,dist[y]+1); } } if(!low) { if(!(--numbs[dist[src]]))dist[n+n+m+l+2]=n+n+m+l+2; ++numbs[dist[src]=mindist]; } return low; } int ISAP(int src,int des) { int ans=0; bfs(src,des); while(dist[0]<n+n+m+l+2)ans+=dfs(src,2e8,des); return ans; } int main() { int i,j; memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&m,&l); for(i=1;i<=m;i++)in(0,i,1); for(i=m+n+n+1;i<=m+n+n+l;i++)in(i,n+n+m+l+1,1); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { int k; scanf("%d",&k); if(k)in(j,m+i,1); } } for(i=1;i<=n;i++) { for(j=1;j<=l;j++) { int k; scanf("%d",&k); if(k)in(m+n+i,m+n+n+j,1); } } for(i=m+1;i<=m+n;i++) { in(i,i+n,1); } printf("%d",ISAP(0,n+n+m+l+1)); return 0; }