题目描述

学校新建了一批宿舍,值日生小A要把所有的空房间都打扫一遍。这些宿舍的布局很奇怪,整个建筑物里所有的房间组成一个N * M的矩阵,每个房间的东南西北四面墙上都有一个门通向隔壁房间。另外有些房间是堆放杂物的,无需打扫。小A想设计若干条打扫路线,使得恰好进出每个需打扫的房间各一次,而且进出每个房间不能通过同一个门。要求每条路线都是一个闭合的环线,并且每条路线经过的房间数大于2。

如下面两图所示均为满足要求的打扫方案(灰色格子为放杂物的房间):

小A发现对于某些房间布局是不存在这样的满足要求的方案的。他请你写一个程序计算一下,对于一种给定的房间布局,满足要求的方案是否存在。

输入输出格式

输入格式:

输入文件的第一行是一个整数T (1 ≤ T ≤ 10),表示该文件中一共有T组数据。接下来依次是T组数据的信息。每组数据的第一行包含两个整数N和M,接下来的N行,每行包含M个字符,表示一个房间布局。字符'.'表示该房间需要打扫,'#'表示该房间是堆放杂物的,无需打扫。

输出格式:

共输出T行,对每组数据输出一行,为"YES"或"NO",表示打扫方案存在与否。

输入输出样例

输入样例#1:

  1. 3 10 12 4
  2. 76 60 87
  3. 78 84 84 84 81 82 72 51 77 57
  4. 85 84 62 87 88 64 81 90 80 66 88 85
  5. 65 83 63 79
  6. 2
  7. 4 5 1
  8. 4 4 2

输出样例#1:

  1. 85.64
  2. 78.00

说明

对50%的数据,3 ≤ N,M ≤ 12

对100%的数据,3 ≤ N,M ≤ 30

Solution

唔,乍看上去比较像是一个搜索题。。然后可以发现的是网络流黑白染色维护这个题并不是一件很困难的事。因为如果我们能从一个门出去,那么我们反过来走一定可以从同一个门进来。这样我们就可以这么实现,把每个黑格子与源点连流量为2的边,每个白格子与汇点连流量为2的边,黑格子和白格子之间用流量为1表示转移。这样就可以轻松实现这道题。

Code

  1. #pragma comment(linker, "/STACK:1024000000,1024000000")
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<queue>
  8. #define re register
  9. #define inf 400000000
  10. #define MAXN 10001
  11. #define MAXM 100001
  12. using namespace std;
  13. int n,s,q,dis[2000011],t,l,cur[200051],m,tot,sum;
  14. struct po
  15. {
  16. int nxt,to,w;
  17. }edge[MAXM];
  18. int head[MAXN],dep[MAXN],num=-1;
  19. char a[101][101];
  20. int id[101][101],nm;
  21. int dx[5]={0,1,0,-1,0};
  22. int dy[5]={0,0,1,0,-1};
  23. inline int read()
  24. {
  25. int x=0,c=1;
  26. char ch=' ';
  27. while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
  28. while(ch=='-')c*=-1,ch=getchar();
  29. while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
  30. return x*c;
  31. }
  32. inline void add_edge(int from,int to,int w)
  33. {
  34. edge[++num].nxt=head[from];
  35. edge[num].to=to;
  36. edge[num].w=w;
  37. head[from]=num;
  38. }
  39. inline void add(int from,int to,int w)
  40. {
  41. add_edge(from,to,w);
  42. add_edge(to,from,0);
  43. }
  44. inline bool bfs()
  45. {
  46. memset(dep,0,sizeof(dep));
  47. queue<int> q;
  48. while(!q.empty())
  49. q.pop();
  50. q.push(s);
  51. dep[s]=1;
  52. while(!q.empty())
  53. {
  54. int u=q.front();
  55. q.pop();
  56. for(re int i=head[u];i!=-1;i=edge[i].nxt)
  57. {
  58. int v=edge[i].to;
  59. if(dep[v]==0&&edge[i].w>0)
  60. {
  61. dep[v]=dep[u]+1;
  62. if(v==t)
  63. return 1;
  64. q.push(v);
  65. }
  66. }
  67. }
  68. return 0;
  69. }
  70. inline int dfs(int u,int dis)
  71. {
  72. if(u==t)
  73. return dis;
  74. int diss=0;
  75. for(re int& i=cur[u];i!=-1;i=edge[i].nxt)
  76. {
  77. int v=edge[i].to;
  78. if(edge[i].w!=0&&dep[v]==dep[u]+1)
  79. {
  80. int check=dfs(v,min(dis,edge[i].w));
  81. if(check>0)
  82. {
  83. dis-=check;
  84. diss+=check;
  85. edge[i].w-=check;
  86. edge[i^1].w+=check;
  87. if(dis==0) break;
  88. }
  89. }
  90. }
  91. return diss;
  92. }
  93. inline int dinic()
  94. {
  95. int ans=0;
  96. while(bfs())
  97. {
  98. for(re int i=0;i<=t;i++)
  99. cur[i]=head[i];
  100. while(int d=dfs(s,inf))
  101. ans+=d;
  102. }
  103. return ans;
  104. }
  105. inline void prepare()
  106. {
  107. memset(head,-1,sizeof(head));
  108. num=-1;nm=0;
  109. sum=0;tot=0;
  110. }
  111. int main()
  112. {
  113. //freopen("date.in","r",stdin);
  114. int T=read();
  115. while(T--){
  116. prepare();
  117. n=read();m=read();
  118. for(re int i=1;i<=n;i++)
  119. for(re int j=1;j<=m;j++){
  120. cin>>a[i][j];
  121. id[i][j]=++nm;
  122. if(a[i][j]!='#') tot++;
  123. }
  124. s=0;t=n*m+1;
  125. if(tot%2==1){cout<<"NO"<<endl;continue;}
  126. for(re int i=1;i<=n;i++)
  127. for(re int j=1;j<=m;j++){
  128. if(i+j&1==1){
  129. if(a[i][j]!='#'){
  130. add(s,id[i][j],2);sum+=2;
  131. for(re int k=1;k<=4;k++){
  132. int lx=i+dx[k],ly=j+dy[k];
  133. if(lx>=1&&lx<=n&&ly>=1&&ly<=m&&a[lx][ly]!='#')
  134. add(id[i][j],id[lx][ly],1);
  135. }
  136. }
  137. }else add(id[i][j],t,2);
  138. }
  139. int d=dinic();
  140. if(d==sum) cout<<"YES"<<endl;
  141. else cout<<"NO"<<endl;
  142. }
  143. return 0;
  144. }

[TJOI2010]打扫房间的更多相关文章

  1. 洛谷P3877 [TJOI2010]打扫房间 解题报告

    首先整理一下条件: 1.恰好进出每个需打扫的房间各一次 2.进出每个房间不能通过同一个门 (其实前两个条件是一回事) 3.要求每条路线都是一个闭合的环线 4.每条路线经过的房间数大于2 让你在一个n* ...

  2. Luogu3877 TJOI2010 打扫房间 二分图、网络流

    传送门 真是菜死了模板题都不会-- 首先\(30 \times 30\)并不能插头DP,但是范围仍然很小所以考虑网络流. 注意每个点都要包含在一个回路中,那么每一个点的度数都必须为\(2\),也就是说 ...

  3. 洛谷$P3877\ [TJOI2010]$打扫房间 网络流

    正解:网络流 解题报告: 传送门$QwQ$ 昂考虑把题目的约束条件详细化?就说每个格点能向四连通连边,问能否做到每个格点度数等于2? $umm$就先黑白染色建两排点呗,然后就$S$向左侧连流量为2的边 ...

  4. P3877 [TJOI2010]打扫房间

    xswl以为是个插头dp,然后发现就是个sb题 相当于就是个匹配.每个格子度数为2,所以可以匹配2个相邻的点.匹配显然的用网络流.最后check有没有不匹配的点即可. #include<bits ...

  5. [ TJOI 2010 ] 打扫房间

    \(\\\) Description 给出一个\(N\times M\) 的网格,一些格子是污点,求是否能用多个封闭的环路覆盖所有不是污点的格点. 封闭的环路覆盖的含义是,每条路径都必须是一个环,且每 ...

  6. 洛咕 P3965 [TJOI2013]循环格

    同tjoi2010 打扫房间,每个点入度,出度都为1,可以向相邻4个点连边,但只有原来存在的边费用为0. // luogu-judger-enable-o2 #include<bits/stdc ...

  7. JVM学习(4)——全面总结Java的GC算法和回收机制

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: 一些JVM的跟踪参数的设置 Java堆的分配参数 -Xmx 和 –Xms 应该保持一个什么关系,可以让系统的 ...

  8. iOS学习19之OC类的扩展

    为一个类扩展功能:1.子类化:2.修改源代码:3.定义协议:4.Category:类目 1.Category 1> Category的作用 Category:也叫分类,类目,是为没有源代码的类扩 ...

  9. uva 107 - The Cat in the Hat

     The Cat in the Hat  Background (An homage to Theodore Seuss Geisel) The Cat in the Hat is a nasty c ...

随机推荐

  1. cxGrid 使用指南 1

    1:cxgrid是应该数据关联的控件,类似dbgrid.2:一般用来查阅表信息,如果要修改的话,直接在上面编辑或添加 非常不方便通常要放几个EDit来对选中的记录进行编辑或添加记录. 因为表一般都有主 ...

  2. SQL转换全角和半角函数

    SQL转换全角和半角函数 CREATE FUNCTION f_Convert( ), --要转换的字符串 @flag bit --转换标志,0转换成半角,1转换成全角 )) AS BEGIN ),@s ...

  3. windows安装oracle11g

    windows上安装oracle11g   1.下载Oracle 11g R2 for Windows的版本 下载地址:https://www.oracle.com/technetwork/datab ...

  4. 关于TNS_ADMIN环境变量

    转自:https://blog.csdn.net/pan_tian/article/details/7699599 很多oracle产品都有自己的TNS文件,如果你的系统里装了多个Oracle的产品的 ...

  5. PAT 甲级 1003Emergency(Dijkstra最短路)

    1003. Emergency (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue As an emerg ...

  6. Powershell Get Domain Mailbox的几种方法

    一.Disconnected Mailboxes 1.Finding Disconnected Mailboxes The first function is called Get-Disconnec ...

  7. Java 之继承和 final 关键字

    继承的概述 继承的特点 super 关键字 函数覆盖 子类的实例化过程 final 关键字 1. 继承的概述 继承是类与类之间的关系. 继承的好处: 提高了代码的复用性 让类与类之间产生了关系, 给第 ...

  8. mongoose连接数据库的两种形式

    不废话,直接 ---------------------- .如果你的应用程序只使用一个数据库, 应该使用 mongoose.connect. 如果您需要创建额外的连接,使用 mongoose.cre ...

  9. Milking Time---poj3616(简单dp)

    题目链接:http://poj.org/problem?id=3616 题意:人从奶牛身上挤奶有m个时间段(1----n),每个时间段包含 s e f 表示从 s 到 e 的这段时间可以获得 f 单位 ...

  10. django博客项目8:文章详情页

    首页展示的是所有文章的列表,当用户看到感兴趣的文章时,他点击文章的标题或者继续阅读的按钮,应该跳转到文章的详情页面来阅读文章的详细内容.现在让我们来开发博客的详情页面,有了前面的基础,开发流程都是一样 ...