CH 2601 - 电路维修 - [双端队列BFS]
题目链接:传送门
描述
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]的更多相关文章
- Luogu P2243 电路维修 双端队列BFS
当转移的代价是0和一个分明不同的权值时,可以用双端队列BFS去跑(你跑最短路也没问题..QWQ) 而对于这道题,边旋转代价是1,不旋转代价是0:可以直接建图最短路,也可以跑BFS 这个题建图很有意思: ...
- CH2601 电路维修(双端队列bfs)建图恶心
CH2601 电路维修 双端队列bfs,其实就是因为只有0和1所以可以直接2维护队列单调性(和优先队列一个道理) 建图的过程需要仔细斟酌(想一想id为什么这么写) 还有,空间要开够(很玄学),我一开始 ...
- 电路维修 (广搜变形-双端队列bfs)
# 2632. 「BalticOI 2011 Day1」打开灯泡 Switch the Lamp On [题目描述] 有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会 ...
- codeforces 1064D 双端队列BFS
双端队列BFS解决的就是路径权值可能为0的图最短路问题,权值为0插入队头,否则插入队尾. 对于这个题,可以看作上下移动的路径的权值为0,左右移动权值为1,而且不能超过规定的步数. 直接广搜求覆盖的点的 ...
- 2601 电路维修 (双端队列bfs\优先队列bfs(最短路))
描述 Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上.Rika的家里有一辆飞行车.有一天飞行车的电路板突然出现了故障,导致无法启动. 电路板 ...
- POJ 3662 Telephone Lines【二分答案+最短路】||【双端队列BFS】
<题目链接> 题目大意: 在一个节点标号为1~n的无向图中,求出一条1~n的路径,使得路径上的第K+1条边的边权最小. 解题分析:直接考虑情况比较多,所以我们采用二分答案,先二分枚举第K+ ...
- HDU - 6386 Age of Moyu (双端队列+bfs)
题目链接 双端队列跑边,颜色相同的边之间的花费为0,放进队首:不同的花费为1,放进队尾. 用Dijkstra+常数优化也能过 #include<bits/stdc++.h> using n ...
- P4554 小明的游戏 (洛谷) 双端队列BFS
最近没有更新博客,全是因为英语,英语太难了QWQ 洛谷春令营的作业我也不会(我是弱鸡),随机跳了2个题,难度不高,还是讲讲吧,学学新算法也好(可以拿来水博客) 第一题就是这个小明的游戏 小明最近喜欢玩 ...
- Codeforces 1064D Labyrinth(双端队列BFS)
题意: 给一个图,"*"不可以走,给你一个起点,限制向左走L次,向右走R次,上下不限制,问你最多可以走到多少个格子 思路: BFS,每次将上下走的策略加入队首,左右加入队尾,(相当 ...
随机推荐
- 云主机IO性能测试
1:数据读取速度 ucloud云主机最低224.8MB/S,最高508.8MB/S,平均410.7MB/S 阿里云主机最低17.4MB/S, 最高189.6MB/S,平均170.6MB/S ...
- Adobe Photoshop for Mac(图像处理软件)破解版安装
1.软件简介 Adobe Photoshop(简称 "PS")是 macOS 系统上一款由 Adobe Systems 开发和发行的图像处理软件.Photoshop 主要处理 ...
- 使用dstat命令的插件查看mysql的io状态
使用dstat竟然还可以查看mysql的状态, man dstat之后发现的,原来在/usr/share/dstat目录下藏有很多python脚本作为插件帮助dstat搜集各类信息. 不过通常有可能会 ...
- intellij idea (Android studio )外部程序 打开某扩展名(格式)
最近在为项目开发写思维导图, 为了留下思考的过程和业务逻辑. 本人使用的工具是很可怜的freemind,所以“脑图”的扩展名是“.mm” 情景: 在intellij idea (Android stu ...
- 译:3.消费一个RESTful Web Service
这节课我们根据官网教程学习如何去消费(调用)一个 RESTful Web Service . 原文链接 https://spring.io/guides/gs/consuming-rest/ 本指南将 ...
- LeetCode: First Missing Positive 解题报告
First Missing Positive Given an unsorted integer array, find the first missing positive integer. For ...
- 【iCore1S 双核心板_ARM】例程五:IWDG看门狗实验——复位ARM
实验原理: STM32内部包含独立看门狗,通过看门狗可以监控程序运行,程序错误 时,未在规定时间喂狗,自动复位ARM.本实验通过按键按下,停止喂狗, 制造程序运行 错误,从而产生复位 . 实验现象: ...
- Fedora Server 21下OpenJdk和Oracle Jdk共存
最新文章:Virson's Blog 参考文章:博客园-三维蚂蚁 Linux公社 1.首先需要下载对应平台的Jdk:Oracle 官网 2.使用yum或rpm命令安装Jdk: yum install ...
- 从浏览器中输入URL到页面加载的发生了什么-转载
转:https://www.cnblogs.com/confach/p/10050013.html 背景 “从浏览器中输入URL到页面加载的发生了什么“,这是一道经典的面试题,涉及到的知识面非常多,但 ...
- 近5年常考Java面试题及答案整理(二)
上一篇:近5年常考Java面试题及答案整理(一) 31.String s = new String("xyz");创建了几个字符串对象? 答:两个对象,一个是静态区的"x ...