NOIP2014提高组day2-T2:寻找道路

2024-01-10 20:04

本文主要是介绍NOIP2014提高组day2-T2:寻找道路,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接

[NOIP2014 提高组] 寻找道路

题目描述

在有向图 G G G 中,每条边的长度均为 1 1 1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:

  1. 路径上的所有点的出边所指向的点都直接或间接与终点连通。
  2. 在满足条件 1 1 1 的情况下使路径最短。

注意:图 G G G 中可能存在重边和自环,题目保证终点没有出边。

请你输出符合条件的路径的长度。

输入格式

第一行有两个用一个空格隔开的整数 n n n m m m,表示图有 n n n 个点和 m m m 条边。

接下来的 m m m 行每行 2 2 2 个整数 x , y x,y x,y,之间用一个空格隔开,表示有一条边从点 x x x 指向点 y y y

最后一行有两个用一个空格隔开的整数 s , t s,t s,t,表示起点为 s s s,终点为 t t t

输出格式

输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出 − 1 -1 1

样例 #1

样例输入 #1

3 2
1 2
2 1
1 3

样例输出 #1

-1

样例 #2

样例输入 #2

6 6
1 2
1 3
2 6
2 5  
4 5
3 4
1 5

样例输出 #2

3

提示

样例 1 解释

如上图所示,箭头表示有向道路,圆点表示城市。起点 1 1 1 与终点 3 3 3 不连通,所以满足题目描述的路径不存在,故输出 − 1 -1 1

样例 2 解释


如上图所示,满足条件的路径为 1 → 3 → 4 → 5 1\to 3\to 4\to 5 1345。注意点 2 2 2 不能在答案路径中,因为点 2 2 2 连了一条边到点 6 6 6,而点 6 6 6 不与终点 5 5 5 连通。

数据范围及约定

  • 对于 30 % 30\% 30% 的数据, 0 < n ≤ 10 0<n\le10 0<n10 0 < m ≤ 20 0<m\le 20 0<m20
  • 对于 60 % 60\% 60% 的数据, 0 < n ≤ 100 0<n\le100 0<n100 0 < m ≤ 2000 0<m\le 2000 0<m2000
  • 对于 100 % 100\% 100% 的数据, 0 < n ≤ 1 0 4 0<n\le 10^4 0<n104 0 < m ≤ 2 × 1 0 5 0<m\le 2\times 10^5 0<m2×105 0 < x , y , s , t ≤ n , x , s ≠ t 0<x,y,s,t\le n,x,s\ne t 0<x,y,s,tn,x,s=t

算法思想

根据题目描述,要求的是满足下面条件的最短路径的长度:

  • 路径上的所有点的出边所指向的点都直接或间接与终点连通

也就是说,该路径上的每个点都能走到终点。那么有哪些点满足条件呢?

  • 首先可以从终点开始反向搜索所有能够达到的点 i i i,将其状态 s t [ i ] st[i] st[i]设置为true
  • 其次遍历每个点 i i i,如果其所有出边所指向的点的状态都为true,那么点 i i i满足条件

当筛选出来所有满足条件的点后,可以通过bfs求起点到终点的最短路径了。

注意,由于正向和反向都要处理,因此需要双向建边,那么如何区分正向边和反向边呢?可以使用链式前向星来保存图,按顺序添加边时,偶数为正向边,奇数为反向边。

时间复杂度

  • 从终点开始反向搜索所有能够达到的点,每条边只会遍历一次,时间复杂度为 O ( n + m ) O(n + m) O(n+m)
  • 遍历每个点,处理其所有出边,时间复杂度为 O ( n + m ) O(n + m) O(n+m)
  • bfs求最短路径,时间复杂度为 O ( n + m ) O(n + m) O(n+m)

代码实现

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1e4 + 5, M = 4e5 + 5;
int h[N], e[M], ne[M], idx;
int dis[N];
bool st[N], f[N];
void add(int a, int b)  // 添加一条边a->b
{e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ; //正向边是偶数,反向边是奇数
}void dfs(int u)
{st[u] = true;for(int i = h[u]; ~ i; i = ne[i]){if(i % 2 == 0) continue; //只搜索反向边int v = e[i];if(!st[v]) dfs(v);}
}int bfs(int s, int t)
{if(!f[s]) return -1; //起点不满足条件memset(dis, 0x3f, sizeof dis);queue<int> q;q.push(s), dis[s] = 0;while(q.size()){int u = q.front(); q.pop();if(u == t) return dis[u];for(int i = h[u]; ~ i; i = ne[i]){if(i % 2) continue; //只搜索正向边int v = e[i];if(!f[v]) continue; //不满足条件if(dis[v] > dis[u] + 1){dis[v] = dis[u] + 1;q.push(v);}}}return -1;
}int main()
{int n, m, s, t;scanf("%d%d", &n, &m);memset(h, -1, sizeof h);while (m -- ){int a, b;scanf("%d%d", &a, &b);add(a, b), add(b, a); //双向建边}scanf("%d%d", &s, &t);dfs(t); //反向搜索每个点的状态//处理每个点出边所指向的点for(int i = 1; i <= n; i ++){f[i] = true;for(int j = h[i]; ~ j; j = ne[j]){//只判断正向边if(j % 2 == 0 && !st[e[j]]){f[i] = false; //i点不满足条件break;}}}//搜索最短路径printf("%d\n", bfs(s, t));return 0;
}

这篇关于NOIP2014提高组day2-T2:寻找道路的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/591917

相关文章

随想录 Day 69 并查集 107. 寻找存在的路径

随想录 Day 69 并查集 107. 寻找存在的路径 理论基础 int n = 1005; // n根据题目中节点数量而定,一般比节点数量大一点就好vector<int> father = vector<int> (n, 0); // C++里的一种数组结构// 并查集初始化void init() {for (int i = 0; i < n; ++i) {father[i] = i;}

leetcode刷题(98)——652. 寻找重复的子树

给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。 两棵树重复是指它们具有相同的结构以及相同的结点值。 示例 1: 1/ \2 3/ / \4 2 4/4 下面是两个重复的子树: 2/4 和 4 因此,你需要以列表的形式返回上述重复子树的根结点。 /*** Definition for a binar

第T2周:彩色图片分类

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 👉 要求: 学习如何编写一个完整的深度学习程序了解分类彩色图片会灰度图片有什么区别测试集accuracy到达72% 🦾我的环境: 语言环境:Python3.8编译器:Jupyter Lab深度学习环境: TensorFlow2 一、 前期准备 1.1. 设置GPU 如果设备上支持GPU就

借助AI快速提高英语听力:如何获得适合自己的听力材料?

英语听力是英语学习中的一个重要组成部分,它对于提高语言理解和交流能力至关重要。可理解性学习(comprehensible input)是语言习得理论中的一个概念,由语言学家Stephen Krashen提出,指的是学习者在理解语言输入的同时,自然而然地习得语言。 Krashen认为,当学习者接触到稍微超出他们当前语言水平的输入时,他们会自然地习得语言。这个稍微超出的部分被称为“i+1”,其中“i

三、MyBatis实践:提高持久层数据处理效率

三、MyBatis实践:提高持久层数据处理效率 目录 一、Mybatis简介 1.1 简介1.2 持久层框架对比1.3 快速入门(基于Mybatis3方式) 二、MyBatis基本使用 2.1 向SQL语句传参 2.1.1 mybatis日志输出配置2.1.2 #{}形式2.1.3 ${}形式 2.2 数据输入 2.2.1 Mybatis总体机制概括2.2.2 概念说明2.2.3 单个简单类型

使用Rcpp提高性能之入门篇

C++能解决的瓶颈问题有: 由于迭代依赖于之前结果,循环难以简便的向量化运算递归函数,或者是需要对同一个函数运算成千上万次R语言缺少一些高级数据结构和算法 我们只需要在代码中写一部分C++代码来就可以处理上面这些问题。后续操作在Windows下进行,你需要安装Rtools,用install.packages("Rcpp")安装新版的Rcpp,最重要一点,你需要保证你R语言时不能是C:/Progr

287 寻找重复数-类似于环形链表II

题目 给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。 你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。 示例 输入:nums = [1,3,4,2,2] 输出:2 解析 这道题倒是可以读懂,就是找到数

如何提高Github的访问速度

最近总觉得Github的访问速度变慢了,导致我的工作效率也肉眼可见的降低了,主要体现在代码数量和质量的双重降低。 为了解决这一问题,我通过网络检索找到了一个非常好的工具,叫做dev-sidecar (https://github.com/docmirror/dev-sidecar), 这个工具的好处在于,图形化界面,完美解决了windows和MacOS上的问题,但是问题也出在图形化界面上,这意味

python | rapidjson,一个实用的 提高JSON处理效率 Python 库!

本文来源公众号“python”,仅用于学术分享,侵权删,干货满满。 原文链接:rapidjson,一个实用的 Python 库! 大家好,今天为大家分享一个实用的 Python 库 - rapidjson。 Github地址:https://github.com/python-rapidjson/python-rapidjson 在现代应用程序开发中,JSON(JavaScript Obj

Java程序之寻找自幂数

题目:         自幂数是指一个 n 位数(3≤n≤7 ),它的每个位上的数字的 n 次幂之和等于它本身(例如:1^3 + 5^3+ 3^3 = 153;1^4+6^4+3^4+4^4=1634)。三位自幂数:水仙花数;四位自幂数:四叶玫瑰数;五位自幂数:五角星数;六位自幂数:六合数;七位自幂数:北斗七星数。要求编写程序,输入一个正整数n(3≤n≤7),按递增顺序输出所有n位自幂数,每个数