题目链接:传送门

描述

Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上。Rika的家里有一辆飞行车。有一天飞行车的电路板突然出现了故障,导致无法启动。
电路板的整体结构是一个R行C列的网格(R,C≤500),如右图所示。每个格点都是电线的接点,每个格子都包含一个电子元件。电子元件的主要部分是一个可旋转的、连接一条对角线上的两个接点的短电缆。在旋转之后,它就可以连接另一条对角线的两个接点。电路板左上角的接点接入直流电源,右下角的接点接入飞行车的发动装置。


Ha'nyu发现因为某些元件的方向不小心发生了改变,电路板可能处于断路的状态。她准备通过计算,旋转最少数量的元件,使电源与发动装置通过若干条短缆相连。不过,电路的规模实在是太大了,Ha'nyu并不擅长编程,希望你能够帮她解决这个问题。

输入格式

输入文件包含多组测试数据。第一行包含一个整数 T 表示测试数据的数目。
对于每组测试数据,第一行包含正整数 R 和 C,表示电路板的行数和列数。
之后 R 行,每行 C 个字符,字符是"/"和"\"中的一个,表示标准件的方向。

输出格式

对于每组测试数据,在单独的一行输出一个正整数,表示所需的缩小旋转次数。
如果无论怎样都不能使得电源和发动机之间连通,输出NO SOLUTION。

样例输入

1
3 5
\\/\\
\\///
/\\\\

样例输出

1

数据范围与约定

对于40% 的数据,R,C≤5。
对于100% 的数据,R,C≤500,T≤5。

题解:

把网格的所有格点(横竖线交叉的点)看做无向图的节点,对于一个一个网格,它有两个对角节点。

假设这两个对角节点,已经有被方格里的短电线连接起来了,那么它们之间建立一条权值为 $0$ 的边;否则就建立权值为 $1$ 的边。

换句话说,这道题相当于:对于这样一张边权只为 $0$ 或 $1$ 的无向图,要求 $s \rightarrow t$ 的最短路。可以通过双端队列BFS完成。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f; int r,c;
char mp[][];
inline int idx(int i,int j) {
return i*(c+)+j;
} struct Edge{
int u,v,w;
Edge(){}
Edge(int _u,int _v,int _w){u=_u,v=_v,w=_w;}
};
vector<Edge> E;
vector<int> G[*];
void init(int l,int r)
{
E.clear();
for(int i=l;i<=r;i++) G[i].clear();
}
void addedge(int u,int v,int w)
{
E.push_back(Edge(u,v,w));
G[u].push_back(E.size()-);
} int d[*],vis[*];
deque<int> Q;
int bfs(int s,int t)
{
memset(d,0x3f,sizeof(d));
memset(vis,,sizeof(vis));
Q.push_back(s), d[s]=;
while(!Q.empty())
{
int u=Q.front(); Q.pop_front();
if(vis[u]) continue;
else vis[u]=;
for(int i=;i<G[u].size();i++)
{
Edge &e=E[G[u][i]]; int v=e.v;
if(vis[v]) continue;
if(d[v]>d[u]+e.w)
{
if(!e.w) Q.push_front(v);
else Q.push_back(v);
d[v]=d[u]+e.w;
}
}
}
return d[t];
} int main()
{
int T;
cin>>T;
while(T--)
{
scanf("%d%d",&r,&c);
init(,idx(r,c));
for(int i=;i<r;i++)
{
scanf("%s",mp[i]);
for(int j=;j<c;j++)
{
if(mp[i][j]=='/')
{
addedge(idx(i+,j),idx(i,j+),);
addedge(idx(i,j+),idx(i+,j),);
addedge(idx(i,j),idx(i+,j+),);
addedge(idx(i+,j+),idx(i,j),);
}
else
{
addedge(idx(i,j),idx(i+,j+),);
addedge(idx(i+,j+),idx(i,j),);
addedge(idx(i+,j),idx(i,j+),);
addedge(idx(i,j+),idx(i+,j),);
}
}
} int ans=bfs(idx(,),idx(r,c));
if(ans==INF) printf("NO SOLUTION\n");
else printf("%d\n",ans);
}
}

一些后续:

代码是不是看着很眼熟?我自己敲着敲着都觉得我不是在敲双端队列BFS,我都以为是在敲优先队列优化Dijkstra……

其实这不是巧合,稍微思考一下就能明白,当我们边权仅为 $0$ 或 $1$ 时,其实不需要优先队列来帮我们控制队列里面每个状态的代价,我们自己就可以通过选择将状态从头部或者尾部push入队列来使得队列保持单调性(因为反正不管在什么时候,队列里面都只存在两种代价 $x$ 和 $x+1$)。

因此,每种状态虽然可能入队多次,但是第一次出队就已经是最小代价(vis标记该状态的最小代价已经求得),后续该状态再次出队直接忽略即可。类比于优先队列优化Dijkstra的时间复杂度,那么双端队列BFS的时间复杂度应当为 $O(|E|)$。

而在本题中,边数与 $RC$ 同阶,故本题双端队列时间复杂度 $O(RC)$。

CH 2601 - 电路维修 - [双端队列BFS]的更多相关文章

  1. Luogu P2243 电路维修 双端队列BFS

    当转移的代价是0和一个分明不同的权值时,可以用双端队列BFS去跑(你跑最短路也没问题..QWQ) 而对于这道题,边旋转代价是1,不旋转代价是0:可以直接建图最短路,也可以跑BFS 这个题建图很有意思: ...

  2. CH2601 电路维修(双端队列bfs)建图恶心

    CH2601 电路维修 双端队列bfs,其实就是因为只有0和1所以可以直接2维护队列单调性(和优先队列一个道理) 建图的过程需要仔细斟酌(想一想id为什么这么写) 还有,空间要开够(很玄学),我一开始 ...

  3. 电路维修 (广搜变形-双端队列bfs)

    # 2632. 「BalticOI 2011 Day1」打开灯泡 Switch the Lamp On [题目描述] 有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会 ...

  4. codeforces 1064D 双端队列BFS

    双端队列BFS解决的就是路径权值可能为0的图最短路问题,权值为0插入队头,否则插入队尾. 对于这个题,可以看作上下移动的路径的权值为0,左右移动权值为1,而且不能超过规定的步数. 直接广搜求覆盖的点的 ...

  5. 2601 电路维修 (双端队列bfs\优先队列bfs(最短路))

    描述 Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上.Rika的家里有一辆飞行车.有一天飞行车的电路板突然出现了故障,导致无法启动. 电路板 ...

  6. POJ 3662 Telephone Lines【二分答案+最短路】||【双端队列BFS】

    <题目链接> 题目大意: 在一个节点标号为1~n的无向图中,求出一条1~n的路径,使得路径上的第K+1条边的边权最小. 解题分析:直接考虑情况比较多,所以我们采用二分答案,先二分枚举第K+ ...

  7. HDU - 6386 Age of Moyu (双端队列+bfs)

    题目链接 双端队列跑边,颜色相同的边之间的花费为0,放进队首:不同的花费为1,放进队尾. 用Dijkstra+常数优化也能过 #include<bits/stdc++.h> using n ...

  8. P4554 小明的游戏 (洛谷) 双端队列BFS

    最近没有更新博客,全是因为英语,英语太难了QWQ 洛谷春令营的作业我也不会(我是弱鸡),随机跳了2个题,难度不高,还是讲讲吧,学学新算法也好(可以拿来水博客) 第一题就是这个小明的游戏 小明最近喜欢玩 ...

  9. Codeforces 1064D Labyrinth(双端队列BFS)

    题意: 给一个图,"*"不可以走,给你一个起点,限制向左走L次,向右走R次,上下不限制,问你最多可以走到多少个格子 思路: BFS,每次将上下走的策略加入队首,左右加入队尾,(相当 ...

随机推荐

  1. 在SharePoint 2013 场中移除服务器,提示 cacheHostInfo is null 错误

    Problem 在SharePoint 2013 场中移除服务器,提示 cacheHostInfo is null 错误 Resolution 这是由于SharePoint 2013中分布式缓存实例( ...

  2. SNF快速开发平台MVC-甘特图

    上个月做了CS框架的甘特图样例,本月框架组人员又实现了BS的甘特图效果,而且效果也很不错哦 图形框可以直接拖拽调整时长时间: 新增节点:

  3. android 性能优化-工具篇

    一.Traceview 使用TraceView主要有两种方式: 1.直接打开DDMS,选择一个进程,然后按上面的“Start Method Profiling”按钮,等红色小点变成黑色以后就表示Tra ...

  4. THE OVERARCHING PROCESS OF TEST DESIGN

    THE OVERARCHING PROCESS OF TEST DESIGN -Test note of “Essential Software Test Design” 2015-08-27 Con ...

  5. rsync安装及部署

    一.服务器端1.yum -y install rsync xinetd 2.vi /etc/xinetd.d/rsync 将yes 修改为no IPV6修改为IPV4 3.vi /etc/rsyncd ...

  6. [转]devm_gpiod_get_optional用法

    https://blog.csdn.net/kris_fei/article/details/78932904

  7. Linux下apache activemq的安装与配置

    ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范 的 JMS Provider实现,尽管JMS规范出台已经是很 ...

  8. Java知多少(87)选择框和单选按钮

    选择框.单选框和单选按钮都是选择组件,选择组件有两种状态,一种是选中(on),另一种是未选中(off),它们提供一种简单的 “on/off”选择功能,让用户在一组选择项目中作选择. 选择框 选择框(J ...

  9. Win7/Win10多用户同时使用远程桌面

    Win7/Win10正常情况下是不允许多用户同时远程的,即一个用户远程进来会把另一个用户踢掉,需要破解. Win7:安装UniversalTermsrvPatch-x64.exe,见https://p ...

  10. ThinkingInJava 学习 之 0000001 一切都是对象

    -- -- -- -- -- -- -- -- -- 大杂烩 -- Java内存布局[图]以及java各种存储区[详解] -- -- -- -- -- -- -- -- -- 1. 用引用操纵对象 在 ...