博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

题解 【ZJOI2009】 假期的宿舍

题面

 

解析

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

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

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

问能否使每人都有床睡。

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

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

所以,我来总结一下:

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

然后就能AC了!

 

 

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

#include<bits/stdc++.h>
using namespace std;

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

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

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]=1;
        if(linker[k]==-1||dfs(linker[k])){
            linker[k]=x;
            return 1;
        }
    }
    return 0;
}

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

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

 

posted @ 2019-03-09 13:43  Hastin  阅读(282)  评论(0编辑  收藏  举报