1. 程式人生 > >洛谷P1402 酒店之王(二分圖)

洛谷P1402 酒店之王(二分圖)

return 酒店 -s main 個數 不同的 條件 clu fine

P1402 酒店之王

題目描述

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<cstring>
#define N 101

using
namespace std; int n,p,q,i,j,RL[N][N],FL[N][N],LB[N],book[N],answer,eat[N]; bool CR[N],visR[N],visF[N],LCR[N],CF[N]; bool room_(int No) { for (int i=1; i<=n; i++) if (RL[No][i]&&!visR[i]) { visR[i]=1; if (book[i]==0||room_(book[i])) { CR[No]
=1; book[i]=No; return 1; } } return 0; } bool food_(int No) { for (int i=1; i<=n; i++) if (FL[No][i]&&!visF[i]) { visF[i]=1; if (eat[i]==0||food_(eat[i])) { CF[No]=1; eat[i]=No; return 1; } } return 0; } int main () { scanf("%d%d%d",&n,&p,&q); for (i=1; i<=n; i++) for (j=1; j<=p; j++) scanf("%d",&RL[i][j]); for (i=1; i<=n; i++) for (j=1; j<=q; j++) scanf("%d",&FL[i][j]); while (1) { for (i=1; i<=n; i++) if (!CR[i]) { for (j=1; j<=n; j++) visR[j]=0; for (j=1; j<=n; j++) visF[j]=0; for (j=1; j<=n; j++) LCR[j]=CR[j]; for (j=1; j<=n; j++) LB[j]=book[j]; if (room_(i)&&food_(i)) { answer++; continue; } else//因為無法匹配所以取消上次所有增廣 { for (j=1; j<=n; j++) CR[j]=LCR[j]; for (j=1; j<=n; j++) book[j]=LB[j]; } } break; } printf("%d\n",answer); return 0; return 0; return 0; }

 

洛谷P1402 酒店之王(二分圖)