题目链接:http://codeforces.com/contest/1272/problem/E

题目大意:

有一个长度为n的数组 \(a\) ,数组坐标从 \(1\) 到 \(n\) 。

假设你现在处于数组中的某一个位置,我们假设这个坐标为 \(i\) ,那么:

如果 \(1 <= i-a[i]\) ,那么你可以从坐标 \(i\) 移动到坐标 \(i-a[i]\) 位置(花费一步);

如果 \(i+a[i]<=n\) ,那么你可以从坐标 \(i\) 移动到坐标 \(i+a[i]\) 位置(同样花费一步)。

对于从 \(1\) 到 \(n\) 的所有坐标 \(i\) 来说,你想要的知道你最少需要几步可以从坐标 \(i\) 移动到一个坐标\(j\) ,

且 \(a[i]\) 和 \(a[j]\) 具有不同的奇偶性(也就是说,如果 \(a[i]\) 是偶数,那么 \(a[j]\) 就是奇数;如果 \(a[i]\) 是奇数,那么 \(a[j]\) 就得是偶数)。

解题思路:

这个问题可以转换成图论模型,然后用广度优先搜索或者最短路算法(Dijkstra或者SPFA算法)进行求解。

这里因为可能有些同学没有学到最短路算法,并且用最短路算法解决广搜可以解决的问题有一点杀鸡用牛刀的感觉(今年CSP-J复赛第4题可以用广搜做然而我也用了最短路SPFA算法),所以我这里还是讲解广度优先搜索解决这个问题。

对于一个边权均为 \(1\) 的图来说,我们通过广度优先搜索得到的就是最短路。因为此时一开始入队列的都是距起点 \(0\) 的点,然后入队列的是距起点 \(1\) 的点,然后入队列的是距起点 \(2\) 的点,……(大家可以自己画图体会一下,此时的广度优先搜索就是一个层次遍历)

然后我们来看怎么使用广度优先搜索解决这个问题。

首先对于 \(a[i]\) 来说,

  • 如果 \(i-a[i] \ge 1\),则从 \(i-a[i]\) 向 \(i\) 连一条边;
  • 如果 \(i+a[i] \le n\),则从 \(i+a[i]\) 向 \(i\) 连一条边。

然后就可以开始我们的搜索了。

在搜索之前我们需要先开两个数组:

  • \(odd[i]\) 表示坐标为 \(i\) 的点到达最近的一个奇数点所需的最少步数;
  • \(even[i]\) 表示坐标为 \(i\) 的点到达最近的一个偶数点所需的最少步数。

我们先来求 \(odd\) 值,

我们从 \(1\) 到 \(n\) 遍历 \(i\) ,

  • 如果 \(a[i]\) 是奇数,则设 \(odd[i]\) 为 \(0\),同时将其加入队列;
  • 否则(\(a[i]\) 为偶数),设 \(odd[i]\) 为无穷大。

接下来每次从队列里面取出一个坐标 \(u\),然后遍历所有 \(u\) 可以到达的点 \(v\) ,如果 \(odd[v] > odd[u]+1\) ,则标记 \(odd[v] = odd[u]+1\) ,同时将 \(v\) 加入队列。

最终每个点的 \(odd\) 值即表示从坐标 \(i\) 出发最少需要花费多少步能够到达一个奇数值得点。

然后我们再来求 \(even\) 值(其实你们会发现是一样的道理),

我们从 \(1\) 到 \(n\) 遍历 \(i\) ,

  • 如果 \(a[i]\) 是偶数,则设 \(odd[i]\) 为 \(0\),同时将其加入队列;
  • 否则(\(a[i]\) 为奇数),设 \(odd[i]\) 为无穷大。

接下来每次从队列里面取出一个坐标 \(u\),然后遍历所有 \(u\) 可以到达的点 \(v\) ,如果 \(odd[v] > odd[u]+1\) ,则标记 \(odd[v] = odd[u]+1\) ,同时将 \(v\) 加入队列。

自此,我们就求解完了 \(odd\) 和 \(even\) 值。

然后我们从 \(1\) 到 \(n\) 遍历坐标 \(i\),

  • 如果 \(a[i]\) 是奇数,输出 \(even[i]\);
  • 如果 \(a[i]\) 是偶数,输出 \(odd[i]\)。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200020;
int n, a[maxn], odd[maxn], even[maxn];
vector<int> g[maxn];
queue<int> que;
int main() {
cin >> n;
for (int i = 1; i <= n; i ++) cin >> a[i];
for (int i = 1; i <= n; i ++) {
if (i-a[i] >= 1) g[ i-a[i] ].push_back(i);
if (i+a[i] <= n) g[ i+a[i] ].push_back(i);
}
// odd
for (int i = 1; i <= n; i ++) {
if (a[i]%2) {
odd[i] = 0;
que.push(i);
}
else odd[i] = -1;
}
while (!que.empty()) {
int u = que.front();
que.pop();
int sz = g[u].size();
for (int i = 0; i < sz; i ++) {
int v = g[u][i];
if (odd[v] == -1 || odd[v] > odd[u] + 1) {
odd[v] = odd[u] + 1;
que.push(v);
}
}
}
// even
for (int i = 1; i <= n; i ++) {
if (a[i] % 2 == 0) {
even[i] = 0;
que.push(i);
}
else even[i] = -1;
}
while (!que.empty()) {
int u = que.front();
que.pop();
int sz = g[u].size();
for (int i = 0; i < sz; i ++) {
int v = g[u][i];
if (even[v] == -1 || even[v] > even[u] + 1) {
even[v] = even[u] + 1;
que.push(v);
}
}
}
for (int i = 1; i <= n; i ++) {
if (i > 1) putchar(' ');
if (a[i] % 2) cout << even[i];
else cout << odd[i];
}
cout << endl;
return 0;
}

CF1272E. Nearest Opposite Parity 题解 广度优先搜索的更多相关文章

  1. Codeforces Round #605 (Div. 3) E. Nearest Opposite Parity(最短路)

    链接: https://codeforces.com/contest/1272/problem/E 题意: You are given an array a consisting of n integ ...

  2. Codeforces Round #605 (Div. 3) E - Nearest Opposite Parity

    题目链接:http://codeforces.com/contest/1272/problem/E 题意:给定n,给定n个数a[i],对每个数输出d[i]. 对于每个i,可以移动到i+a[i]和i-a ...

  3. Codeforces Round #605 (Div. 3) E - Nearest Opposite Parity (超级源点)

  4. Codeforces 1272E (Nearest Opposite Parity,反向建边)

    题意:给你n个数,每个数的值为a[i],每个点可以从i这号点跳转至(i - a[i]) 或 (i + a[i])点,点的范围为[1,n],然后问的是从偶数点跳至奇数点,从奇数点跳至偶数点的最少次数是多 ...

  5. 算法与数据结构基础 - 广度优先搜索(BFS)

    BFS基础 广度优先搜索(Breadth First Search)用于按离始节点距离.由近到远渐次访问图的节点,可视化BFS 通常使用队列(queue)结构模拟BFS过程,关于queue见:算法与数 ...

  6. Leetcode之广度优先搜索(BFS)专题-279. 完全平方数(Perfect Squares)

    Leetcode之广度优先搜索(BFS)专题-279. 完全平方数(Perfect Squares) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ar ...

  7. SDUT-2124_基于邻接矩阵的广度优先搜索遍历

    数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给定一个无向连通图 ...

  8. 用一道模板题理解多源广度优先搜索(bfs)

    题目: //多元广度优先搜索(bfs)模板题详细注释题解(c++)class Solution { int cnt; //新鲜橘子个数 int dis[10][10]; //距离 int dir_x[ ...

  9. 图的广度优先搜索(BFS)

    把以前写过的图的广度优先搜索分享给大家(C语言版) #include<stdio.h> #include<stdlib.h> #define MAX_VERTEX_NUM 20 ...

随机推荐

  1. java文件操作 之 创建文件夹路径和新文件

    一:问题 (1)java 的如果文件夹路径不存在,先创建: (2)如果文件名 的文件不存在,先创建再读写;存在的话直接追加写,关键字true表示追加 (3)File myPath = new File ...

  2. 安装visualStudio 出现 cant install Microsoft.TeamFoundation.OfficeIntegration.Resources

    本文告诉大家在安装 VisualStudio 时出现cant install Microsoft.TeamFoundation.OfficeIntegration.Resources如何安装 如果在安 ...

  3. 记一次sublime text3更新 注册码失效问题和永久解决~

    前言: 一段时间不用sublime,打开提示我更新,不知怎么想的鬼使神差给点了~ 然后喵喵喵??? 取消 一会又出来了 受不了啦 搞事开整~ 正文: 本想直接找个注册码完事,奈何好多都用不了,想着再更 ...

  4. iptables禁止强制访问指定的站点

    要使192.168.52.0/24网络内的计算机(这此计算机的网关应设为192.168.52.10)强制访问指定的站点,在做为防火墙的计算机(192.168.52.10)上应添加以下规则: 1. 打开 ...

  5. codeforces1238-div2

    C 目前在h的高度,1~h每一个台阶要么处于out的状态,要么处于in的状态,问最少改变几个台阶的状态,使得能够从h的高度到0. 下降的唯一的方式,拉动lever,h-1的状态取反,下落的最大的高度不 ...

  6. title与h1的区别、b与strong的区别、i与em的区别?

    title与h1的区别 定义: title是网站标题, h1是文章主题 作用: title概括网站信息,可以直接告诉搜索引擎和用户这 个网站是关于什么主题和内容的,是显示在网页Tab栏里的: h1突出 ...

  7. ThinkPHP5.1接收post、get参数

    我们要先认识的是请求对象Request类 <?php//要用Request类 第一步就要引入他,才能在当前控制器上使用//知识点:use 与 namespace前面不可有空格等其他操作.name ...

  8. Python--day69--ORM外键的正向查询和反向查询

    什么是正向查询,什么是方向查询?

  9. JDBC 时间处理

    Java中用类java.util.Date对日期/时间做了封装,此类提供了对年.月.日.时.分.秒.毫秒以及时区的控制方法,同时也提供一些工具方法,比如日期/时间的比较,前后判断等. java.uti ...

  10. Mac PHPStorm清除SVN配置缓存