洛谷 P2055 [ZJOI2009]假期的宿舍
题目描述
学校放假了 · · · · · · 有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题。比如 A 和 B 都是学校的学生,A 要回家,而 C 来看B,C 与 A 不认识。我们假设每个人只能睡和自己直接认识的人的床。那么一个解决方案就是 B 睡 A 的床而 C 睡 B 的床。而实际情况可能非常复杂,有的人可能认识好多在校学生,在校学生之间也不一定都互相认识。我们已知一共有 n 个人,并且知道其中每个人是不是本校学生,也知道每个本校学生是否回家。问是否存在一个方案使得所有不回家的本校学生和来看他们的其他人都有地方住。
输入输出格式
输入格式:
第一行一个数 T 表示数据组数。接下来 T 组数据,每组数据第一行一个数n 表示涉及到的总人数。接下来一行 n 个数,第 i
个数表示第 i 个人是否是在校学生 (0 表示不是,1 表示是)。再接下来一行 n 个数,第 i 个数表示第 i 个人是否回家 (0
表示不会家,1 表示回家,注意如果第 i 个人不是在校学生,那么这个位置上的数是一个随机的数,你应该在读入以后忽略它)。接下来 n 行每行 n
个数,第 i 行第 j 个数表示 i 和 j 是否认识 (1 表示认识,0 表示不认识,第 i 行 i 个的值为
0,但是显然自己还是可以睡自己的床),认识的关系是相互的。
输出格式:
对于每组数据,如果存在一个方案则输出 “ ^_^ ”(不含引号) 否则输出“T_T”(不含引号)。(注意输出的都是半角字符,即三个符号的 ASCII 码分别为94,84,95)
输入输出样例
1
3
1 1 0
0 1 0
0 1 1
1 0 0
1 0 0
^_^
说明
对于 30% 的数据满足 1 ≤ n ≤ 12。
对于 100% 的数据满足 1 ≤ n ≤ 50,1 ≤ T ≤ 20。
多组数据!!!
Solution:
这道题一看就类似于二分图匹配的问题,既可以用匈牙利算法来做也可以用最大流做。
1、用匈牙利算法。思路就是把每个是学校里的学生和他们自己的床位相连且边权为1(实际实现时可以都连,只需要在增广时判断就行了),再统计需要在学校住的同学的人数(因为只有这些人需要床位),然后把相互认识的人和床位相连且边权为1(实际实现时这里也可以不必判断是否是学校的学生,只需要增广时特判就行了)。。。关键的增广时,记得判断:必须是留在学校的学生或者外来的学生,才能以他为起点进行增广。最后若增广累加的值等于一开始统计的需要在学校住的人数,则可以,否则不行。
代码:
#include<bits/stdc++.h>
#define il inline
using namespace std;
const int N=,inf=;
int T,n,l[N],k[N],cnt,pre[N],ans,tot,h[N];
bool vis[N];
struct edge{
int to,net;
}e[N*];
il void add(int u,int v)
{
e[++cnt].to=v,e[cnt].net=h[u],h[u]=cnt;
}
il bool find(int u)
{
for(int i=h[u];i;i=e[i].net){
int v=e[i].to;
if(!vis[v]){
vis[v]=;
if(!pre[v]||find(pre[v])){pre[v]=u;return ;}
}
}
return ;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
ans=tot=;cnt=;
memset(h,,sizeof(h));
memset(pre,,sizeof(pre));
for(int i=;i<=n;i++)scanf("%d",&l[i]);
for(int i=;i<=n;i++){
scanf("%d",&k[i]);
if(l[i]&&!k[i])add(i,i+n);
}
for(int i=;i<=n;i++)
if(!l[i]||(l[i]&&!k[i]))tot++;
int x;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
scanf("%d",&x);
if(x&&l[j])add(i,j+n);
}
for(int i=;i<=n;i++)
if(!l[i]||(l[i]&&!k[i])){
memset(vis,,sizeof(vis));
if(find(i))ans++;}
// printf("%d %d\n",ans,tot);
if(ans==tot)printf("^_^\n");
else printf("T_T\n");
}
return ;
}
2、用最大流做。思路与匈牙利算法的类似,但是附加源点S(连向需要住校的人并赋权值为1)和汇点T(由每个床位连向T并赋权值为1),然后与匈牙利算法相同,统计需要住校的人数,加边时注意必须是需要住校的且认识的才能与床位相连(该回家的肯定是回家好,这样不占床位),最后增广累加答案,若等于需要住校的人数则可以,否则不行。
代码:
#include<bits/stdc++.h>
#define il inline
using namespace std;
const int N=,inf=;
int T,n,s,t=,l[N],k[N],cnt=,dis[N],h[N],ans,tot;
queue<int>q;
struct edge{
int to,net,v;
}e[N*];
il void add(int u,int v,int w)
{
e[++cnt].to=v,e[cnt].v=w,e[cnt].net=h[u],h[u]=cnt;
e[++cnt].to=u,e[cnt].v=,e[cnt].net=h[v],h[v]=cnt;
}
il bool bfs()
{
memset(dis,-,sizeof(dis));
q.push(s),dis[s]=;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=h[u];i;i=e[i].net)
if(dis[e[i].to]==-&&e[i].v>)dis[e[i].to]=dis[u]+,q.push(e[i].to);
}
return dis[t]!=-;
}
il int dfs(int u,int op)
{
if(u==t)return op;
int flow=,used=;
for(int i=h[u];i;i=e[i].net)
{
int v=e[i].to;
if(dis[v]==dis[u]+&&e[i].v>)
{
used=dfs(v,min(op,e[i].v));
if(!used)continue;
flow+=used,op-=used;
e[i].v-=used,e[i^].v+=used;
if(!op)break;
}
}
if(!flow)dis[u]==-;
return flow;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=;i<=N;i++)h[i]=,l[i]=,k[i]=;
//memset(e,0,sizeof(e));
cnt=;ans=tot=;
int x;
for(int i=;i<=n;i++)scanf("%d",&l[i]);
for(int i=;i<=n;i++){
scanf("%d",&x);
if(l[i]==)k[i]=x;
}
for(int i=;i<=n;i++){
if(!k[i])add(s,i,),tot++;
if(l[i])add(i+n,t,);
}
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
scanf("%d",&x);
if(x==||i==j)add(i,j+n,);
}
while(bfs())ans+=dfs(s,inf);
if(ans==tot)printf("^_^\n");
else printf("T_T\n");
}
return ;
}
洛谷 P2055 [ZJOI2009]假期的宿舍的更多相关文章
- 洛谷P2055 [ZJOI2009]假期的宿舍
P2055 [ZJOI2009]假期的宿舍 题目描述 学校放假了 · · · · · · 有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题.比如 A 和 B 都是学校的学生,A ...
- 洛谷——P2055 [ZJOI2009]假期的宿舍
P2055 [ZJOI2009]假期的宿舍 学校放假了 · · · · · · 有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题.比如 A 和 B 都是学校的学生,A 要回家,而 ...
- 洛谷P2055 [ZJOI2009]假期的宿舍 题解
题目链接: https://www.luogu.org/problemnew/show/P2055 分析: 这道题比较简单,二分图的练习题(当然最大流同理). 易得我们可以将人放在一侧,床放在一侧. ...
- 洛谷P2055 [ZJOI2009]假期的宿舍 [二分图最大匹配]
题目描述 学校放假了 · · · · · · 有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题.比如 A 和 B 都是学校的学生,A 要回家,而 C 来看B,C 与 A 不认识. ...
- 洛谷$P2055\ [ZJOI2009]$ 假期的宿舍 最大流
正解:最大流 解题报告: 传送门$QwQ$ 这种一看就很网络流鸭,直接说咋建图趴. 考虑把在校的人拆成人和床.$S$连向所有不回家的人,所有床连向$T$,认识的人之间人向床连边,跑个最大流就成. $o ...
- 洛谷 P2055 【假期的宿舍】
题库 :洛谷 题号 :2055 题目 :假期的宿舍 link :https://www.luogu.org/problem/P2055 首先明确一下:校内的每个学生都有一张床(只是校内的有) 思路 : ...
- BZOJ1433或洛谷2055 [ZJOI2009]假期的宿舍
BZOJ原题链接 洛谷原题链接 对于每个需要床位的人向他能睡的床连边,然后就是二分图最大匹配模板了. 这里用匈牙利算法. #include<cstdio> #include<cstr ...
- 洛谷2055 [ZJOI2009]假期的宿舍
题目描述 学校放假了 · · · · · · 有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题.比如 A 和 B 都是学校的学生,A 要回家,而 C 来看B,C 与 A 不认识. ...
- 洛谷 2055 [ZJOI2009]假期的宿舍——二分图匹配
题目:https://www.luogu.org/problemnew/show/P2055 #include<iostream> #include<cstdio> #incl ...
随机推荐
- python字符串、列表、字典的常用方法
一.python字符串的处理方法 >>> str = ' linzhong LongXIA ' >>> str.upper() #字符串str全部大写 ' LINZ ...
- Yii2 Gridview 动态显示行或列和action列
我们知道Yii中的GridView组件是非常好用的. 某些情况要动态显示某列,这时候就要用到visible属性 'propString' => ['attribute' => 'prope ...
- MSP-EZ430U_02板子测试使用
1. 实物如下 2. 先上电,显示驱动没安装 3. 找到驱动的位置,不过实际上安装IAR for msp430之后,驱动就自动的识别了.
- cookie和session在Django中的应用
1 会话跟踪技术 什么是会话跟踪 我们需要先了解一下什么是会话!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应.例如你给10086打个电话,你就是客户端,而1008 ...
- 学习笔记之glog的使用
下载源码,使用cmake编译,最后得到了32位的静态库 glog.lib 使用库时要注意添加以下预定义: GLOG_NO_ABBREVIATED_SEVERITIES; GOOGLE_GLOG_DLL ...
- IO多路复用(二) -- select、poll、epoll实现TCP反射程序
接着上文IO多路复用(一)-- Select.Poll.Epoll,接下来将演示一个TCP回射程序,源代码来自于该博文https://www.cnblogs.com/Anker/p/3258674.h ...
- Qt 编程指南
Qt 编程指南 持续关注一本正在编写的Qt编程指南,期待作者早日完成创作.
- 4.airflow测试
1.测试sqoop任务1.1 测试全量抽取1.1.1.直接执行命令1.1.2.以shell文件方式执行sqoop或hive任务1.2 测试增量抽取2.测试hive任务3.总结 当前生产上的任务主要分为 ...
- ADAS芯片解决方案汇总
ADAS(高级辅助驾驶系统),是指利用安装于车上各式各样的传感器,在第一时间收集车内的环境数据,进行静.动态物体的辨识.侦测与追踪等技术上的处理,从而能够让驾驶者在最快的时间察觉可能发生的危险. 在过 ...
- 针对某一网站的UI进行分析
本周课上教学通过对PM(项目经理)的学习,我了解到PM 对项目所有功能的把握, 特别是有关的UI内容.最差的UI, 体现了团队的组织架构:其次, 体现了产品的内部结构:最好, 体现了用户的自然需求. ...