题解 【ZJOI2009】 假期的宿舍
阅读原文时间:2023年07月11日阅读:1

解析

这其实就是个二分图匹配的水题(虽然我还是爆零了)

这题的意思就是说,有x个人,y张床(x,y不确定),

每个人只能睡在指定的几张床上,

问能否使每人都有床睡。

所以,直接二分图匹配,看最大匹配是否大于行了啊啊!(当然,用网络流也可以。)

然而,却出现了一些玄学错误(导致本次考试全体爆零)。

所以,我来总结一下:

  • 多组数据要记得清零!
  • 注意如果第 i 个人不是在校学生,那么这个位置上的数是一个随机的数,应该在读入以后忽略它
  • 连边的时候要住意有些校外的人没床。

然后就能AC了!

上AC代码(虽然感觉没什么用):

#include
using namespace std;

inline int read(){
int sum=,f=;char ch=getchar();
while(ch>'' || ch<''){if(ch=='-')f=-;ch=getchar();} while(ch>='' && ch<=''){sum=sum*+ch-'';ch=getchar();}
return f*sum;
}

struct node{
int next,to;
}e[];
int T;
int n,s[]/*是否在校*/,a[]/*是否回家*/;
int m,head[],cnt=;
int f[][];
int linker[],vis[];

void add(int x,int y){
e[++cnt].to=head[x];
e[cnt].next=y;
head[x]=cnt;
}

bool dfs(int x){
for(int i=head[x];i;i=e[i].to){
int k=e[i].next;
if(vis[k]) continue;
vis[k]=;
if(linker[k]==-||dfs(linker[k])){
linker[k]=x;
return ;
}
}
return ;
}

bool hungarian(int m){
memset(linker,-,sizeof(linker));
int sum=;
for(int i=;i<=n;i++){ if(!a[i]){ memset(vis,,sizeof(vis)); if(dfs(i)) sum++; } } if(sum>=m) return ;
return ;
}

int main(){
// freopen("dormitory.in","r",stdin);
// freopen("dormitory.out","w",stdout);
T=read();
while(T--){
memset(head,,sizeof(head));
memset(e,,sizeof(e));
memset(f,,sizeof(f));
memset(a,,sizeof(a));
cnt=;
n=read();m=n;
for(int i=;i<=n;i++)
s[i]=read();
for(int i=;i<=n;i++){
int x=read();
if(s[i]) a[i]=x;
}
for(int i=;i<=n;i++) m-=a[i];
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
f[i][j]=read();
}
f[i][i]=;
}
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(f[i][j]&&s[j]) add(i,j+n);
}
}
if(hungarian(m)) printf("%c%c%c\n",,,);
else printf("T_T\n");
}
return ;
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章