酒店之王
題目描述
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; }
?