题目链接:传送门

描述

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. Linux下的两种磁盘分区工具的使用

    如何使用fdisk和parted分区工具来进行硬盘分区,下面我来说一下在Linux系统中这两种硬盘分区工具的使用方法:     ----------fdisk分区工具----------       ...

  2. 海量数据拆分到nosql系统的一种方案

    获取某用户的好友最新动态. 我们大体上来说先按照用户ID将用户的好友一致性哈希到几个mongodb集群,然后把用户的最新信息也存储到mongodb中.然后利用消息系统保持数据库中的数据和mongdb中 ...

  3. [Aaronyang] 写给自己的WPF4.5 笔记8[复杂数据处理三步曲,数据视图精讲1/3]

    真的好累了 ,笑了.做回自己吧       -------------      Aaronyang技术分享 www.ayjs.net 博文摘要: 详细介绍了WPF中视图的种类和开始学之前的准备工作 ...

  4. 本地搭建Wooyun漏洞库环境

    众所周知,wooyun上有太多含金量的漏洞了,虽然互联网上也有相关的漏洞资源分享,但是万一有朝一日也被和谐了就又麻烦了,最放心的方式就是漏洞库放在本地,在本地搭建一套环境最好不过了,以下操作演示了如何 ...

  5. System.SerializableAttribute

    System.SerializableAttribute 串行化是指存储和获取磁盘文件.内存或其他地方中的对象.在串行化时,所有的实例数据都保存到存储介质上,在取消串行化时,对象会被还原,且不能与其原 ...

  6. SpringMVC(Springboot)返回文件方法

    https://blog.csdn.net/Lynn_coder/article/details/79953977 ****************************************** ...

  7. requestNextAnimationFrame兼容主浏览器方法

    window.requestNextAnimationFrame = (function () { var originalRequestAnimationFrame = undefined, wra ...

  8. <BEA-141281> <unable to get file lock, will retry ...>

    原文:http://gdutlzh.blog.163.com/blog/static/164746951201291903824812/ <BEA-141281> <unable t ...

  9. Linux expect 使用(免密登录跳板机)

    登录公司的跳板机是挺麻烦的事,首先要ssh,然后输入密码,有的公司可能还要动态密码,前两步操作都是固定的,所以能免去前两步的操作就会方便很多(线上出问题也能尽快登上去,免得紧张密码一直输错,哈哈哈). ...

  10. Guava Lists.transform踩坑小记<转>

    1.问题提出 1.前段时间在项目中用到Lists.transform返回的List,在对该list修改后发现修改并没有反映在结果里,研究源码后发现问题还挺大.下面通过单步调试的结果来查看Guava L ...