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

来源:互联网 发布:1 10月进出口数据 编辑:程序博客网 时间:2024/05/17 12:56

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


0 0