\(\\\)

Description


给出一个\(N\times M\) 的网格,一些格子是污点,求是否能用多个封闭的环路覆盖所有不是污点的格点。

封闭的环路覆盖的含义是,每条路径都必须是一个环,且每一个格点正好只被一条路径覆盖。图是四联通的。

  • \(N,M\le 30\)

\(\\\)

Solution


一开始以为是插头,后来发现只能做\(50\%\)的数据......

将图黑白染色。注意到一个合法的图一定满足每个格点正好进出各一次。每个黑点只能由周围至多的四个白点进出,白点同理。

所以理论上应该是每个格点都正好达到,向一个异色格点流一股流,从一个异色个点流入一股流,且两个异色格点不为同一个点。

将问题转化一下,把白色格点流向黑色格点的流反向。

这样每个黑色格点正好流出两股流,每个白色格点正好流入两股流,我们再加上源汇,源向黑色点流量为 \(2\) ,白色点向汇流量为 \(2\) 。

这样就转化为满流的判定问题了。

\(\\\)

Code


#include<cmath>
#include<queue>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 910
#define R register
#define gc getchar
#define inf 2000000000
using namespace std; inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} bool mp[N][N];
int n,m,s,t,g,tot,cnt,sum,hd[N],h[N],dp[N],num[35][35]; struct edge{int to,nxt,w;}e[N*100]; inline void add(int u,int v,int w){
e[++tot].to=v; e[tot].w=w;
e[tot].nxt=hd[u]; hd[u]=tot;
} queue<int> q; inline bool bfs(){
memset(dp,0,sizeof(dp));
dp[s]=1; q.push(s);
while(!q.empty()){
int u=q.front(); q.pop();
for(R int i=hd[u],v;i;i=e[i].nxt)
if(e[i].w&&!dp[v=e[i].to]){
dp[v]=dp[u]+1; q.push(v);
}
}
return dp[t];
} int dfs(int u,int flow){
if(u==t||!flow) return flow;
R int res=0,tmp;
for(R int &i=h[u],v;i;i=e[i].nxt)
if(e[i].w&&(dp[v=e[i].to]==dp[u]+1)){
tmp=dfs(v,min(e[i].w,flow-res));
e[i].w-=tmp; e[i^1].w+=tmp; res+=tmp;
if(res==flow) return flow;
}
return res;
} inline int dinic(){
int res=0;
while(bfs()){
memcpy(h,hd,sizeof(hd));
res+=dfs(s,inf);
}
return res;
} inline void work(){
n=rd(); m=rd();
cnt=g=s=sum=0;
t=n*m+1; tot=1;
memset(hd,0,sizeof(hd));
char c;
for(R int i=1;i<=n;++i)
for(R int j=1;j<=m;++j){
c=gc(); while(c!='.'&&c!='#') c=gc();
mp[i][j]=(c!='#');
num[i][j]=++cnt;
if(c!='#') ++g;
if((i+j)&1){
if(mp[i][j]){add(s,cnt,2);add(cnt,s,0);sum+=2;}
}
else if(mp[i][j]){add(cnt,t,2);add(t,cnt,0);}
}
if(g&1){puts("NO");return;}
for(R int i=1;i<=n;++i)
for(R int j=1;j<=m;++j)
if(mp[i][j]&&((i+j)&1)){
if(i!=1&&mp[i-1][j]){add(num[i][j],num[i-1][j],1);add(num[i-1][j],num[i][j],0);}
if(i!=n&&mp[i+1][j]){add(num[i][j],num[i+1][j],1);add(num[i+1][j],num[i][j],0);}
if(j!=1&&mp[i][j-1]){add(num[i][j],num[i][j-1],1);add(num[i][j-1],num[i][j],0);}
if(j!=m&&mp[i][j+1]){add(num[i][j],num[i][j+1],1);add(num[i][j+1],num[i][j],0);}
}
int ans=dinic();
puts((ans==sum)?"YES":"NO");
} int main(){
int t=rd();
while(t--) work();
return 0;
}

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

  1. [TJOI2010]打扫房间

    题目描述 学校新建了一批宿舍,值日生小A要把所有的空房间都打扫一遍.这些宿舍的布局很奇怪,整个建筑物里所有的房间组成一个N * M的矩阵,每个房间的东南西北四面墙上都有一个门通向隔壁房间.另外有些房间 ...

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

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

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

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

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

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

  5. [TJOI 2010]中位数

    Description 给定一个由N个元素组成的整数序列,现在有两种操作: 1 add a 在该序列的最后添加一个整数a,组成长度为N + 1的整数序列 2 mid 输出当前序列的中位数 中位数是指将 ...

  6. P3877 [TJOI2010]打扫房间

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

  7. C#笔记2:重构

    转: 最常用的重构指导 参考:http://www.cnblogs.com/KnightsWarrior/archive/2010/06/30/1767981.html,本文示例代码多来自此处: 参考 ...

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

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

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

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

随机推荐

  1. fastjson过滤器简单记录

    fastjson过滤器,该字段可以将转化的json字段遍历,方便实用 1 /** * 通用输出json * @param object * @return json字符串 */ public Stri ...

  2. Ubuntu 16.04安装Intel显卡驱动(解决Intel HD Graphics 630显卡驱动问题)

    一般Ubuntu都默认包含了Intel显卡的驱动,如果没有,那么先确定是不是显卡太高,比如I7第7代的CPU核显在Ubuntu 16.04中是没有的,导致画面会很卡,原因是Linux 4.4内核不包含 ...

  3. 打开google 新地址

    还在为谷歌打不开而发愁吗? 那就试试这个吧 91.213.30.151

  4. 复制class文件到as中出现非法字符,须要class,interface货enum

    问题如题,出现此情况是在导入eclipse项目到Android Studio出现这种错误, 非法字符: '\ufeff' 解决方式|错误: 须要class, interface或enum,查阅后了解到 ...

  5. C#项目的生成事件及批处理文件

    一个C#项目,如果为同一个解决方案的其他项目所引用,则其编译后,会将DLL拷贝到引用项目中:但如果它并不被其他项目引用,但又想编译后能够自动将生成的东西拷贝过去,可以在项目的生成事件中,写上一些批处理 ...

  6. 解决Hibernate4执行update操作,不更新数据的问题

    后台封装java对象,使用hibernate4再带的update,执行不更新数据,不报错. 下面贴出解决方法: 失败的方法 hibernate自带update代码:(失效) Session sessi ...

  7. 2015ACM/ICPC Asia Regional Changchun Online /HDU 5438 图

    Ponds                                   Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 1310 ...

  8. 【bzoj1787】&【bzoj1832】[Ahoi2008]Meet 紧急集合 & 聚会

    bzoj1787就是bzoj1832 bzoj1832 空间和时间少了一些... 求三个结点到一个结点距离之和最小的结点以及距离和 求出两两lca,其中有两个相同,答案则为另一个 感觉就是一大暴力.. ...

  9. 蓝桥 PREV-34 历届试题 矩阵翻硬币

      历届试题 矩阵翻硬币   时间限制:1.0s   内存限制:256.0MB      问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第 ...

  10. continue 的理解

    continue 一般出现循环体的开始部分,或中间部分,而不可能是结尾(没有必要,正常执行也会退出本次循环): 1. continue 的替代方案 while (true){ if (A || B){ ...