洛谷P3877 [TJOI2010]打扫房间 解题报告
首先整理一下条件:
1、恰好进出每个需打扫的房间各一次
2、进出每个房间不能通过同一个门
(其实前两个条件是一回事)
3、要求每条路线都是一个闭合的环线
4、每条路线经过的房间数大于2
让你在一个n*m的矩阵中,找出是否能按照约定方案打扫全部指定房间。
首先不难得出一个结论:有奇数个需要打扫的房间时一定无解。
证明?
每一次打扫都要满足条件3和4,而闭合的环线为多边形,显然必须对称(即通过平移可得到矩形),不难看出:每一次都能且只能打扫偶数个房间。
然后稍作分析,发现每个格子的度为2(即进入此房再出去)。
考虑建图。
一个房间上下左右有门,我们自然而然想到一个点向周围四个连边,就构成了黑白染色的模型。
一个矩阵中的房间最多用两条路线打扫即可。
每个点都要走到。
所以每个点都会向上下左右异色格点流出1,同时也会接受另一个点的流入。
我们这时将白点流向黑点的流反向,这样每个白点流入2,每个黑点流出2。
于是每个点有2的流量,来说明可以有两条边和它相连。
黑点都向S连边,白点都向T连边
然后图建好了,开始跑网络流,如果满流就证明所有的点都进,出过一次,打扫完毕,输出yes;否则no
建图总结:
- 节点含义:房间
- 边的含义:打扫路线
- 边如何相连:四连通
- 源点S:矩阵外一点
- 汇点T:矩阵外一点
代码:
#include<cstdio>
#include<vector>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
#define inf 0x7fffffff
int n,m,s,t,ans;
int gx[5]={0,0,-1,0,1};
int gy[5]={0,-1,0,1,0};
//int gy[5]={0,-1,1,0,0};
//int gx[5]={0,0,0,-1,1};
int d[1000],id[105][105];
char a[105][105];
struct edge
{
int to,val,rev;
edge(int _to,int _val,int _rev)
{
to=_to;
val=_val;
rev=_rev;
}
};
vector<edge>e[1000];
void add(int x,int y,int w)
{
e[x].push_back(edge(y,w,e[y].size()));
e[y].push_back(edge(x,0,e[x].size()-1));
}
bool bfs()
{
memset(d,-1,sizeof(d));
queue<int>q;
q.push(s);
d[s]=0;
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=0;i<e[x].size();i++)
{
int y=e[x][i].to;
if((d[y]==-1)&&e[x][i].val)
{
q.push(y);
d[y]=d[x]+1;
}
}
}
if(d[t]==-1)
return 0;
else
return 1;
}
int dfs(int x,int low)
{
if(x==t||low==0)return low;
int totflow=0;
for(int i=0;i<e[x].size();i++)
{
int y=e[x][i].to;
int rev=e[x][i].rev;
if((d[y]==(d[x]+1))&&e[x][i].val)
{
int a=dfs(y,min(low,e[x][i].val));
e[x][i].val-=a;
e[y][rev].val+=a;
low-=a;
totflow+=a;
if(low==0)return totflow;
}
}
if(low!=0)d[x]=-1;
return totflow;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
for(int i=0;i<=1000;i++)
e[i].clear();
int cnt=0,tot=0,sum=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
id[i][j]=++cnt;
if(a[i][j]=='.')tot++;
}
}
s=0;
t=cnt+1;
if(tot%2==1)
{
printf("NO\n");
continue;
}
if((n==1)||(m==1))
{
printf("NO\n");
continue;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]=='.')
{
if(((i+j)%2)==1)
{
add(s,id[i][j],2);
sum+=2;
for(int k=1;k<=4;k++)
{
int nx=i+gx[k];
int ny=j+gy[k];
if((nx>=1)&&(nx<=n)&&(ny>=1)&&(ny<=m)&&(a[nx][ny]!='#'))
add(id[i][j],id[nx][ny],1);
}
}
else
{
add(id[i][j],t,2);
}
}
}
}
ans=0;
while(bfs())
{
ans+=dfs(s,inf);
}
if(ans==tot)
{
printf("YES\n");
}
else
printf("NO\n");
}
return 0;
}
洛谷P3877 [TJOI2010]打扫房间 解题报告的更多相关文章
- 洛谷$P3877\ [TJOI2010]$打扫房间 网络流
正解:网络流 解题报告: 传送门$QwQ$ 昂考虑把题目的约束条件详细化?就说每个格点能向四连通连边,问能否做到每个格点度数等于2? $umm$就先黑白染色建两排点呗,然后就$S$向左侧连流量为2的边 ...
- 洛谷_Cx的故事_解题报告_第四题70
1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h> struct node { long x,y,c; ...
- 洛谷 P2317 [HNOI2005]星际贸易 解题报告
P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...
- 洛谷 P3802 小魔女帕琪 解题报告
P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...
- 洛谷 P2606 [ZJOI2010]排列计数 解题报告
P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...
- 洛谷1303 A*B Problem 解题报告
洛谷1303 A*B Problem 本题地址:http://www.luogu.org/problem/show?pid=1303 题目描述 求两数的积. 输入输出格式 输入格式: 两个数 输出格式 ...
- 洛谷 P1457 城堡 The Castle 解题报告
P1457 城堡 The Castle 题目描述 我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张"幸运爱尔兰" ...
- 洛谷 P3084 [USACO13OPEN]照片Photo 解题报告
[USACO13OPEN]照片Photo 题目描述 农夫约翰决定给站在一条线上的\(N(1 \le N \le 200,000)\)头奶牛制作一张全家福照片,\(N\)头奶牛编号\(1\)到\(N\) ...
- 洛谷 P1502 窗口的星星 解题报告
P1502 窗口的星星 题目背景 小卡买到了一套新房子,他十分的高兴,在房间里转来转去. 题目描述 晚上,小卡从阳台望出去,"哇~~~~好多星星啊",但他还没给其他房间设一个窗户, ...
随机推荐
- 从wireshark中学网络分析(一)
http://blog.csdn.net/nk_test/article/details/56509688 http://blog.csdn.net/nk_test/article/details/5 ...
- Qt https 用户认证authenticationRequired()
用QNetworkAccessManager以POST方式访问https需要用户认证,所以用SIGNAL(authenticationRequired(QNetworkReply *, QAuthen ...
- c# 停靠窗体
public partial class FrmAnchor : Form, IMessageFilter { public FrmAnchor(Control parentControlc, Con ...
- QT使用MySql的配置(使用addLibraryPath载入插件),编译QT的MySql驱动问题及解决方案(自己使用libmysql.lib进行编译mysql.pro,万不得已可以查看Makefile.Debug以解决问题)
2010/04/23:Fixes : 更新批处理,以兼容WIN7. 第一次系统地玩QT,于是诞生了此预备式: [QT版本4.6.0(VS2008编译版),开发平台推荐使用Qt Creator(最新1. ...
- fullpage.js使用方法
了解: [1]之所以叫做fullpage,是因为它可以全屏滚动,拥有强大的功能. [2]它依赖于jQuery库,所以在使用fullpage之前先引入jQuery库. 使用: [1]<link r ...
- MakerDAO 代币解释:DAI, WETH, PETH, SIN, MKR(一)
Maker DAO Token Maker DAO 系统是由多个智能合约 ( Sai Tap, Sai Tub, Vox, Medianiser, etc.), 和 ERC-20 代币组成. 他们一起 ...
- 解决Linux和Windos不同步的问题
两种方式: 一:在windos上进行操作 (1).cmd中输入如下命令 Reg add HKLM\SYSTEM\CurrentControlSet\Control\TimeZone ...
- 系统学习 Java IO (三)----文件类 File
目录:系统学习 Java IO---- 目录,概览 Java IO API 中的 File 类可以访问基础文件系统. 使用 File 类,可以: 检查文件或目录是否存在. 如果目录不存在,创建一个目录 ...
- java常用基础(一)
Java常用基础(一) 原文写于2017-12-02 输入输出 //输入 Scanner in = new Scanner(new BufferedInputStream(System.in)); i ...
- Programming In Lua 第三章
1, 2, 3, 4, 5,lua中,只有false和nil为假,0和空字符串为真. 6, 7,