给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环。
所有边的长度都是 1,点的编号为 1∼n。
请你求出 1 号点到 n 号点的最短距离,如果从 1 号点无法走到 n 号点,输出 −1。
输入格式
第一行包含两个整数 nn和 m。
接下来 m 行,每行包含两个整数 a 和 b,表示存在一条从 a 走到 b 的长度为 1的边。
输出格式
输出一个整数,表示 1 号点到 n 号点的最短距离。
数据范围
1≤n,m≤105
输入样例:
4 5
1 2
2 3
3 4
1 3
1 4
输出样例:
1
本题使用BFS,由于是求到n号点的最短距离且每条边距离都为1,所以可以采取每次向外扩展一层,扩展到的点就是最近的点,一直扩展到n号点则找到一条到n号点的最短路径,输出距离即可.
重边和自环不需要特殊处理,因为扩展某个点之前要看他有没有被访问过,没被访问过就不扩展,所以遇到有重边点i第一次会扩展更新距离d[i],第二次访问d[i]!=-1,所以不会加入队列,对结果无影响.
自环同理,第一次扩展会更新距离,第二次访问发现d[i]!=-1就不会更新距离.
/*
* @Author: ACCXavier
* @Date: 2021-04-17 09:46:50
* @LastEditTime: 2021-04-24 10:32:17
* Bilibili https://space.bilibili.com/7469540
* @keywords: 图中点的层次 https://www.acwing.com/problem/content/849/
*/
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5+10;
int n,m;
//存图
int h[N],e[N],ne[N],idx;
//存距离 d[i]1号点到n的距离
int d[N];
//存点的队列
int q[N];
void add(int a,int b){
e[idx] = b, ne[idx] = h[a],h[a] = idx ++;
}
int bfs(){
int hh = 0,tt = 0;
q[0] = 1;//0的位置是1号点 按题目要求
memset(d,-1,sizeof d);//初始化距离-1
d[1] = 0;//1号点到1号点距离为0
while(hh <= tt){
int t = q[hh++];//当前点
for(int i = h[t]; i != -1; i = ne[i]){
int j = e[i];//取点j
if(d[j]==-1){//未被访问过,也就是可用
d[j] = d[t] + 1;//j点距离等于当前点距离+1
q[++tt] = j;//入队
}
}
}
return d[n];//!这里不是d[n-1] 从1开始
}
int main(){
cin>>n>>m;
memset(h,-1,sizeof h);//链表也要初始化
int a,b;
for(int i = 0; i < m; ++ i ){
scanf("%d%d",&a,&b);
add(a,b);
}
cout<<bfs()<<endl;
return 0;
}