BZOJ 1433: [ZJOI2009]假期的宿舍 二分图最大匹配

1433: [ZJOI2009]假期的宿舍

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2812  Solved: 1189
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

1
3
1 1 0
0 1 0
0 1 1
1 0 0
1 0 0

Sample Output

ˆ ˆ

HINT

对于30% 的数据满足1 ≤ n ≤ 12。
对于100% 的数据满足1 ≤ n ≤ 50,1 ≤ T ≤ 20。


一眼就能看出是二分图最大匹配

再来就该想怎么连边

:将需要座位的人向可提供的床位连边就可以了

注意: 一定不要像我一样因为忘记重置邻接表调一上午。。。


#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<queue>
#include<set>
#include<map>
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return f*x;
}
const int N=60;
int n,ans,ecnt,last[N],match[N];
bool ins[N],book[N],vis[N],ls[N];
struct EDGE {int fr,to,nt;}e[N<<5];
inline void add(int u,int v)
{e[++ecnt]=(EDGE){u,v,last[u]};last[u]=ecnt;}
bool hungray(int u)
{
	for(int i=last[u];i;i=e[i].nt)
	if(!vis[e[i].to])
	{
		vis[e[i].to]=1;
		if(!match[e[i].to]||hungray(match[e[i].to]))
		{
			match[e[i].to]=u;
			return 1;
		}
	}
	return 0;
}
int main()
{
	int T=read(),x;
	while(T--)
	{
		memset(book,0,sizeof(book));
		memset(match,0,sizeof(match));
		memset(last,0,sizeof(last)); 
		n=read();int tot=0;ans=0;
		for(int i=1;i<=n;i++)ins[i]=read();
		for(int i=1;i<=n;i++)
		{
			ls[i]=read();
			if (!ins[i]||(ins[i]&&!ls[i]))tot++;
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				x=read();
				if(x&&((ins[i]&&!ls[i])||!ins[i])&&ins[j])add(i,j);
			}
			if(ins[i]&&!ls[i])add(i,i);
		}
		for(int i=1;i<=n;i++)
		{memset(vis,0,sizeof(vis));if(hungray(i))ans++;}
		if(ans==tot)puts("^_^");else puts("T_T");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值