[BZOJ1433] [ZJOI2009]假期的宿舍

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。

题目分析:

这题一看就是二分图最大匹配 但是建图非常恶心
分三种情况:
1:在校学生并且不回家 向自己所有认识的在校学生的床连一条边 包括自己
2:不在校学生 向所有自己认识的在校学生的床连一条边
3:在校学生,并且回家 连一条自己家里的床(i->n+i)
最后数组开够 时刻注意不在校学生没有自己的床

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
int head[1200],to[300010],net[300010],hom[1100],sch[1100];
int n,t,tot;
bool vis[1200];
int line[1200];
int map[100][1000];
void init()
{
	tot=0;
	n=0;
	memset(head,0,sizeof head);
	memset(to,0,sizeof to);
	memset(map,0,sizeof map);
	memset(net,0,sizeof net);
	memset(hom,0,sizeof hom);
	memset(sch,0,sizeof sch);
	memset(line,0,sizeof line);
	memset(vis,0,sizeof vis);
}
void add(int x,int y)
{
	net[++tot]=head[x];
	to[tot]=y;
	head[x]=tot;
}
int dfs(int x)
{
	for(int i=head[x];i;i=net[i])
		if(!vis[to[i]])
		{
			vis[to[i]]=1;
			if(line[to[i]]==0||dfs(line[to[i]]))
			{
				line[to[i]]=x;
				return 1;
			}
		}
	return 0;
}
int check()
{
	for(int i=1;i<=n;i++)
	{
		memset(vis,0,sizeof vis);
		if(!dfs(i)) return 0;
	}
	return 1;
}
char a=84;
int main()
{
	scanf("%d",&t);
	while(t)
	{
		t--;
		init();
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&sch[i]);
		for(int i=1;i<=n;i++) scanf("%d",&hom[i]);
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				scanf("%d",&map[i][j]);
		for(int i=1;i<=n;i++)
		{
			if(sch[i]==1)
			{
				if(hom[i]==1) add(i,n+i);
				else for(int j=1;j<=n;j++)
					if((i==j)||(sch[j]&&map[i][j])) add(i,j);
			}
			else 
			{
				for(int j=1;j<=n;j++)
					if(sch[j]&&map[i][j]) add(i,j);
			}
		}	
		if(!check()) printf("%c%c%c\n",a,a+11,a);
		else printf("%c%c%c\n",a+10,a+11,a+10);
	}
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注