题目
给定一个n个点m条边的有向图,图中可能存在重边和自环。
所有边的长度都是1,点的编号为1~n。
请你求出1号点到n号点的最短距离,如果从1号点无法走到n号点,输出-1。
输入格式
第一行包含两个整数n和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(广度优先遍历),使用的是队列结构,而深度优先遍历则使用的是栈的结构. 基于这种数据结构,广度优先遍历只能要么模拟队列/要么直接使用队列,而深度优先遍历却能够直接使用递归函数.因为递归函数本质上就是调用栈来进行的.
算法解析
很简单,算法要做的就是
初始化队列:先给队列传入一个初始值
只要队列非空,就进行如下操作
- 弹出队头
- 把队头连接的子节点判断一下(当然判断的方式自己定),只要没被用过,就插入队尾.
仅此而已
源代码
package test;
import java.util.*;
class Main{
static int N=100010;
//链表四件套
static int index=0;
static int[] h=new int[N];
static int[] e=new int[N];
static int[] ne=new int[N];
//队列两件套
static int[] q=new int[N];
//本题专用 记录距离
static int[] d=new int[N];
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
while(m-->0){
int a=sc.nextInt();
int b=sc.nextInt();
add(a,b);
}
System.out.print(bfs(n));
}
public static void add(int a,int b){
e[++index]=b;
ne[index]=h[a];
h[a]=index;
}
//队的初始化最好放在这里
public static int bfs(int n){
int hh=0;
int tt=0;
q[0]=1;
Arrays.fill(d,-1);
d[1]=0;
while(hh<=tt){
int x=q[hh++];
for(int i=h[x];i!=0;i=ne[i]){
int j=e[i];
if(d[j]==-1){
q[++tt]=j;
d[j]=d[x]+1;
}
}
}
return d[n];
}
}
备注
这里我们使用Arrays.fill函数,让d[]
数组全部填充-1,这样因为我们自己弄的一定都是>=0的,所以我们看到-1就知道我们没有操作过.