1、题目描述
给定一个n个点m条边的有向图,图中可能存在重边和自环。
所有边的长度都是1,点的编号为1~n。
请你求出1号点到n号点的最短距离,如果从1号点无法走到n号点,输出-1。
输入格式
第一行包含两个整数n和m。
接下来m行,每行包含两个整数a和b,表示存在一条从a走到b的长度为1的边。
输出格式
输出一个整数,表示1号点到n号点的最短距离。
数据范围
1≤n,m≤1051≤n,m≤105
输入样例:
4 5 1 2 2 3 3 4 1 3 1 4
输出样例:
1
2、分析
所有边的长度都是1,所以可以使用宽度搜索BFS。
1) 通过队列实现bfs,从原点出发,往指向的点进行枚举,并且相继进栈
2) 队列中元素出队列时,枚举下一层
3) 数组d[]记录1到i最短距离时的值,若值为-1表示没有遍历过该点
注意:边权都是1才能使用bfs搜最短路
这里的队列我们使用数组模拟队列的实现方法。
3、代码
import java.util.*;
import java.io.*;
public class Main{
static int N = 100010;
static int[] queue = new int[N];
static int[] h = new int[N]; //单链表
static int[] e = new int[N];
static int[] ne = new int[N];
static int idx;
static int[] d = new int[N]; //表示从结点1到结点i的最短距离
static boolean[] visit = new boolean[N];
static int n;
static void store(int a, int b) {
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++;
}
static int bfs() {
int hh = 0, tt = -1; //队列头指针、尾指针
//使用数组模拟的队列
d[1] = 0;
visit[1] = true;
queue[++ tt] = 1;
while(hh <= tt) { //队列不空
int u = queue[hh ++]; //取出队头元素
//扩展队头
for(int i = h[u];i != -1;i = ne[i]) {
int j = e[i];
if(!visit[j]) { // d[j] == -1
queue[++ tt] = j;
d[j] = d[u] + 1;
visit[j] = true;
}
}
}
return d[n]; //表示从结点1到结点n的最短距离
}
public static void main(String[] args) {
Scanner in = new Scanner(new InputStreamReader(System.in));
n = in.nextInt();
int m = in.nextInt();
Arrays.fill(d, -1); //初始化距离
Arrays.fill(h, -1); //初始化单链表表头指针
for(int i = 0;i < m;i ++) {
int a = in.nextInt();
int b = in.nextInt();
store(a, b);
}
System.out.println(bfs());
}
}
当然,我们也可以使用Queue这个数据结构来之间操作。
package cn.acwing.搜索与图论;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;
public class 图中点的层次 {
static int N = 100010;
static int[] h = new int[N]; //单链表,存储的是结点的下标
static int[] e = new int[N];
static int[] ne = new int[N];
static int idx;
static int[] d = new int[N]; //表示从结点1到结点i的最短距离
static int n;
static Deque<Integer> queue = new LinkedList<>();
static int bfs() {
queue.add(1);
d[1] = 0;
while(queue.size() > 0) {
Integer head = queue.poll();
for(int i = h[head]; i != -1;i = ne[i]) {
int j = e[i];
if(d[j] == -1) {
d[j] = d[head] + 1;
queue.add(j);
}
}
}
return d[n];
}
public static void main(String[] args) {
Scanner in = new Scanner(new InputStreamReader(System.in));
n = in.nextInt();
int m = in.nextInt();
//先初始化
Arrays.fill(h, -1);
Arrays.fill(d, -1);
for(int i = 0;i < m;i ++) {
int a = in.nextInt();
int b = in.nextInt();
store(a, b);
}
System.out.println(bfs());
}
private static void store(int a, int b) {
e[idx] = b;
ne[idx] = h[a];
h[a] = idx;
idx ++;
}
}