洛谷 P2055 [ZJOI2009]假期的宿舍
阿新 • • 發佈:2019-01-02
題目:假期的宿舍
emm……
為什麼二分圖會寫錯這麼多次?
我不會說是因為我建圖建錯了的……
思路:
我好像沒有說過我建錯了圖,二分圖匹配好像沒有什麼好說的,所以這裡說下建圖的問題。
首先,我們考慮用學生和空床匹配。
床的個數一定等於本校學生人數,因為不管學生是否離校,他們的床都在。
需要和床匹配的人數就是 沒有回家的本校學生人數 + 非本校學生。
所以,一個人 i 可以和 j的床 連邊的條件,當且僅當 j 是本校學生,且i是 沒有回家的本校學生人數 或本校學生。
然後在這張圖上跑二分圖模板就好了。
用最大流或者匈牙利隨便啦,這裡給出匈牙利程式碼。
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define read(x) scanf("%d",&x)
#define maxn 50
int n;
int sc[maxn+5],hm[maxn+5];
vector<int> a[maxn+5]; //i -> bedlist
int mth[maxn+5];
bool use[maxn+5];
bool dfs(int x) {
if(use[x]) return false;
use[x]=true;
for(int i= 0;i<a[x].size();i++) {
int y=a[x][i];
if((!mth[y])||dfs(mth[y])) {
mth[y]=x;
return 1;
}
}
return 0;
}
int main() {
int T;
read(T);
while(T--) {
int n;
read(n);
for(int i=1; i<=n; i++) a[i].clear();
memset(mth,0,sizeof(mth));
for(int i=1; i<=n; i++) read(sc[i]);
for (int i=1; i<=n; i++) read(hm[i]);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++) {
int z;
read(z);
if(sc[i]&&hm[i]) continue;
if(!sc[j]) continue;
if(!z) continue;
a[i].push_back(j);
}
for(int i=1;i<=n;i++) if(sc[i]&&!hm[i]) a[i].push_back(i);
int cnt=n;
for(int i=1; i<=n; i++) if(sc[i]&&hm[i]) cnt--;
int ans=0;
for(int i=1; i<=n; i++) {
memset(use,0,sizeof(use));
if(dfs(i)) ans++;
}
if(ans==cnt) printf("^_^");
else printf("T_T");
printf("\n");
}
return 0;
}