1433: [ZJOI2009]假期的宿舍
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 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
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;
}