1. 程式人生 > >洛谷 P2055 [ZJOI2009]假期的宿舍

洛谷 P2055 [ZJOI2009]假期的宿舍

題目:假期的宿舍


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; }