• 题解 【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
    ",94,95,94);
            else printf("T_T
    ");
        }
        return 0;
    }
  • 相关阅读:
    网易163邮箱被盗号找回经历
    C++中基类的析构函数为什么要用virtual虚析构函数
    像linux ls命令一样优雅地打印
    【Linux】- 六个超赞的字符画生成器
    linux欢迎界面 /etc/motd
    Linux 的 FIGlet 指令产生 ASCII Art 大型文字教学
    趣玩 Linux:四个生成字符图案(字符画)的命令
    案例参考手册-第四章 Curses字符界面.docx
    读取键盘输入流改为原始模式
    centos 7配置系统调度isolcpus(软中断绑定)
  • 原文地址:https://www.cnblogs.com/zsq259/p/10500464.html
Copyright © 2020-2023  润新知