洛谷 P2055 [ZJOI2009]假期的宿舍

版权声明:欢迎转载欢迎评论! https://blog.csdn.net/rabbit_ZAR/article/details/85240633

题目:假期的宿舍


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

猜你喜欢

转载自blog.csdn.net/rabbit_ZAR/article/details/85240633