您的位置:首页 > 其它

BZOJ1433 [ZJOI2009]假期的宿舍

2016-08-13 12:26 393 查看

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。

正解:二分图匹配(匈牙利算法)
解题报告:
  直接跑匈牙利算法。注意连边的关系,只有当i需要床位而且j可能提供床位时才连边,而且i不回家时,向自己连边。
  注意最大匹配的时候vis数组不能记i本身,因为可以匹配自己。细节问题。

//It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#ifdef WIN32
#define OT "%I64d"
#else
#define OT "%lld"
#endif
using namespace std;
typedef long long LL;
const int MAXN = 51;
int n,ans,cnt,a[MAXN][MAXN],b[MAXN],c[MAXN],match[MAXN];
bool vis[MAXN];

inline int getint()
{
int w=0,q=0;
char c=getchar();
while((c<'0' || c>'9') && c!='-') c=getchar();
if (c=='-')  q=1, c=getchar();
while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
return q ? -w : w;
}

inline bool dfs(int x){
//不能加这一步!!!可能会匹配自己!!!
//vis[x]=1
for(int i=1;i<=n;i++) {
if(a[x][i] && !vis[i]) {
vis[i]=1;
if(!match[i] || dfs(match[i])) {
match[i]=x;
// match[x]=i;不能标记两边
return true;
}
}
}
return false;
}

inline void work(){
int T=getint();
while(T--) {
memset(a,0,sizeof(a));memset(match,0,sizeof(match));
n=getint(); ans=0; cnt=0;
for(int i=1;i<=n;i++) b[i]=getint(); for(int i=1;i<=n;i++) c[i]=getint();
for(int i=1;i<=n;i++) if(!b[i] || (b[i]&&!c[i])) cnt++;//统计需要床位的人数
int x;
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
x=getint();
if(x && ((b[i] && !c[i]) || !b[i] ) &&b[j]) //表示i需要床位,而且i、j认识,并且j可能提供床位
a[i][j]=1;
}
if(b[i] && !c[i]) a[i][i]=1;//留校的在校生肯定可以睡自己床上
}
for(int i=1;i<=n;i++) {
memset(vis,0,sizeof(vis));
if(dfs(i)) ans++;
}
if(ans==cnt) printf("^_^\n");
else printf("T_T\n");
}
}

int main()
{
work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: