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

相关文章

寻找身高相近的小朋友

题目描述: 小明今年升学到小学一年级,来到新班级后发现其他小朋友们身高参差不齐,然后就想基于各小朋友和自己的身高差对他们进行排序,请帮他实现排序。 输入描述: 第一行为正整数H和N,0<H<200,为小明的身高,0<N<50,为新班级其他小朋友个数。第二行为N个正整数H1-HN,分别是其他小朋友的身高,取值范围0<Hi<200(1<=i<=N),且N个正整数各不相同。 输出描述: 输出

键盘快捷键:提高工作效率与电脑操作的利器

键盘快捷键:提高工作效率与电脑操作的利器 在数字化时代,键盘快捷键成为了提高工作效率和优化电脑操作的重要工具。无论是日常办公、图像编辑、编程开发,还是游戏娱乐,掌握键盘快捷键都能带来极大的便利。本文将详细介绍键盘快捷键的概念、重要性、以及在不同应用场景中的具体应用。 什么是键盘快捷键? 键盘快捷键,也称为热键或快捷键,是指通过按下键盘上的一组键来完成特定命令或操作的方式。这些快捷键通常涉及同

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

如何提高 GitHub 的下载速度

如何提高 GitHub 的下载速度 文章目录 如何提高 GitHub 的下载速度1. 注册账号2. 准备好链接3. 创建仓库4. 在码云上下载代码5. 仓库更新了怎么办 一般来说,国内的朋友从 GitHub 上面下载代码,速度最大是 20KB/s,这种龟速,谁能忍受呢? 本文介绍一种方法——利用“码云”,可以大大提高下载速度,亲测有效。 1. 注册账号 去“码云”注册一

【第0006页 · 数组】寻找重复数

【前言】本文以及之后的一些题解都会陆续整理到目录中,若想了解全部题解整理,请看这里: 第0006页 · 寻找重复数         今天想讨论的一道题在 LeetCode 上评论也是颇为“不错”。有一说一,是道好题,不过我们还是得先理解了它才算真正的好题。这里我们展示一种使用二进制的做法,希望能帮到你哟! 【寻找重复数】给定一个包含 n + 1 个整数的数组 nums ,其数字都

如何提高开发的效率,让老板不知所措的给你发工资

设计模式 UML JSP 编程 数据结构 1.你可能会常常发现,写了一段代码后,编译程序时是一大堆的出错 (原因:语法不熟)  ──别担心,这是每个程序员必须经历的事,这时候你就需要更大的耐心及细心,对每一行代码进行仔细人阅读并改正,这个很重要,这可以培养你的理解代码能力,所以要常读程序,不要等到程序运行以后才知道你的程序的结果。  ──如何避免:在写代码以前,要认真的学习计算机语

Java预备知识 - day2

1.IDEA的简单使用与介绍 1.1 IDEA的项目工程介绍 Day2_0904:项目名称 E:\0_code\Day2_0904:表示当前项目所在路径 .idea:idea软件自动生成的文件夹,最好不要动 src:src==sourse→源,我们的源代码就放在这个文件夹之内 Day2_0904.iml:也是自动生成的文件,不要动 External Libraries:外部库 我这

Java开发实例大全提高篇——Applet的应用

开发十年,就只剩下这套架构体系了! >>>    第21章  Applet的应用 21.1  Applet在html中的使用 实例549  在html中显示Applet HtmlShowApplet.java     public void paint(Graphics g){         g.drawString("html文件已经运行", 50, 50);// 绘制文本

Java开发实例大全提高篇——Java安全

开发十年,就只剩下这套架构体系了! >>>    第6篇  Java安全与Applet应用篇 第20章  Java安全 20.1  Java对称加密 实例531  使用BASE64加密     public static String encryptBASE64(byte[] data) {         //加密数据         return (new BASE64Encoder()

2024国赛论文拿奖快对照这几点及评阅要点,勿踩雷区!(国赛最后冲刺,提高获奖概率)

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 2024“高教社杯”全国大学生数学建模竞赛已过去第三个夜晚,小伙伴们都累了没有,如果感到思维滞涩,别忘了稍作休息,放松一下自己,准备迎接国赛非常重要的收尾阶段——论文。 国赛这几天的努力最后都