【BZOJ1433】[ZJOI2009] 假期的宿舍(二分图匹配入门)

news/2024/7/6 16:46:45

点此看题面

大致题意:\(n\)个学生,其中一部分是在校学生,一部分不是,而在校学生中一部分回家,一部分不回家,并且我们用一个01矩阵表示学生之间相互认识关系。已知每个学生只能睡自己认识的人的床(当然,他也可以睡自己的床),问是否有一个方案使得所有学生都有床睡。

建图

这道题是一道图论题。对于这种图论题,我们首先要考虑的便是建图。

不难想到,我们可以将每个人与其能睡的床连一条边,即:

  • 对于一个在校不回家的学生\(i\),我们将\(i\)与自己的床连一条边。
  • 对于一个在校且不回家不在校的学生\(i\),如果他认识一个在校的学生\(j\),我们将\(i\)\(j\)的床连一条边。

之所以上面要强调不回家,是因为对于回家的学生,在给他连边是没有任何意义的。

而这张图建成之后,应该不难发现它是一张二分图,那么原题就变成了一道求二分图最大匹配的题目,就可以用匈牙利算法来解决了。

再看一眼数据范围,\(n≤50\),那么匈牙利算法的\(O(n^2)\)复杂度在这道题目中不是轻松跑跑吗?

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define LL long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++)
#define N 50
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
char ff[100000],*A=ff,*B=ff;
using namespace std;
int n,m,ee=0,lnk[N+5],vis[N+5],s[N+5],SchoolStudent[N+5],BackHome[N+5];
struct edge
{
    int to,nxt;
}e[N*N+5]; 
inline void read(int &x)
{
    x=0;static char ch;
    while(!isdigit(ch=tc()));
    while(x=(x<<3)+(x<<1)+ch-48,isdigit(ch=tc()));
}
inline bool GetPoint(int x,int t)//为编号为x的点寻找一个匹配
{
    register int i;
    for(i=lnk[x];i;i=e[i].nxt)//枚举每一个与x相邻的节点
    {
        if(!(vis[e[i].to]^t)) continue;//如果这个节点已经访问过了,就跳过
        vis[e[i].to]=t;//否则,标记这个节点已访问
        if(!s[e[i].to]||GetPoint(s[e[i].to],t))//如果这个节点没被匹配,或者与这个节点匹配的节点能找到一个新的节点匹配
        {
            s[e[i].to]=x;//标记这个节点与x匹配
            return true;//找到一个匹配,返回true
        }
    }
    return false;//说明找不到匹配,返回false
} 
int main()
{
    register int i,j,T,x,ok;read(T);
    while(T--)
    {
        for(read(n),ee=0,ok=i=1;i<=n;++i) vis[i]=s[i]=lnk[i]=0;//多组数据,记得初始化
        for(i=1;i<=n;++i) read(SchoolStudent[i]);//读入每个学生是否是在校学生
        for(i=1;i<=n;++i) {read(BackHome[i]);if(!SchoolStudent[i]) BackHome[i]=0;}//读入每个学生是否回家,如果不是在校学生,默认其不回家
        for(i=1;i<=n;++i)
        {
            for(j=1;j<=n;++j)
            {
                read(x);
                if((x&&!BackHome[i]&&SchoolStudent[j])||(i==j&&SchoolStudent[i]&&!BackHome[i])) add(i,j);//如果i认识j,i不回家,且j是在校学生;或者i=j,i是在校学生,且i不回家,将i与j连一条边
            }
        }
        for(i=1;i<=n;++i) if(!BackHome[i]&&!GetPoint(i,i)) {ok=0;break;}//如果某个学生不回家,且找不到床,那么就说明没有使每个人都有床的方案
        puts(ok?"^_^":"T_T");
    }
    return 0;
}

转载于:https://www.cnblogs.com/chenxiaoran666/p/BZOJ1433.html


http://www.niftyadmin.cn/n/4556963.html

相关文章

‘Basic‘ attribute type should not be a container 解决办法

问题: 原因:我项目中使用的是spring data jpa ,框架会把该属性当成数据库的一个字段,而set不是mysql的数据类型; 解决办法: 1.加Transient注解 2.看了别的文章说是配置表关系

C语言高手请近

d);} ||| 貌似有许多方法 简便就是循环取出单个编为数组就可以了 其次建议使用String取值 比较容易些 但你要取出后转换一下Int c b a &d);a(a9)%10;b(b9)%10;c(c9)%10;d(d9)%10;ia;ac;ci;bj;jd;db;printf("%d%d%d%d/n" &c &b &a j;scanf("%d%d…

windows上部署springboot项目(jar包)

1.用idea将项目打成jar包 2.在target文件夹下找到jar文件 2.右键jar包选中show in explorer打开jar包所在文件夹 3.打开cmd进入jar包所在目录,选中目录栏输入cmd回车即可 4.输入java -jar 项目文件名.jar 5.针对第4部的懒人模式----bat批处理文件 *在jar包目录下创建一个.…

maven source 1.3 中不支持泛型 解决办法

maven打包时始终出现以下提示&#xff1a;1、-source 1.3 中不支持泛型&#xff08;请使用 -source 5 或更高版本以启用泛型&#xff09;List<User> userList new ArrayList<User>();2、-source 1.3 中不支持注释&#xff08;请使用 -source 5 或更高版本以启用注释…

关于git仓库过大,仅想维护自己需要的部分代码

##1.新建workspace&#xff0c;初始化 git init##2.远程加载库(已经存在跳过) git remote add -f origin http://XXXX.XXXXXX.XXX/XXXX##3.允许使用sparse checkout git config core.sparsecheckout true##4.将需要下载的文件路径加入到配置文件 echo subfolderName/subfol…

mysql(三)InnoDB之自适应hash索引

目录 前言自适应哈希索引 (Adaptive Hash Index, AHI)既然是哈希&#xff0c;key 是什么&#xff0c;value 是什么&#xff1f;为啥叫 “自适应 (adaptive)****” 哈希索引&#xff1f;系统会不会判断失误&#xff0c;是不是一定能加速&#xff1f; 创建自定义的hash索引思路示…

Java 多线程学习随笔

博文内容中字符过多&#xff0c;拒绝显示 转载于:https://www.cnblogs.com/zhangrj9/p/9872633.html

怎么才可以学好C语言

||| 先把基本语法熟悉后 用你学的语言实现一些简单的算法 基本语法熟练后 常看别人写的代码.多练就行了.有什么不会的问我.QQ107416106 多写程序...只有这样 ||| 先编200个小程序 ||| 先只是将书上的源程序 照打进 编译器里 运行 然后对其中的你不明白的地方进行改动 看运行的结…