搜索与图论 - 图中点的层次

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搜最短路

 

搜索与图论 - 图中点的层次_第1张图片

 

这里的队列我们使用数组模拟队列的实现方法。

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 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 ++;
	}

}

 

你可能感兴趣的:(算法基础学习,数据结构,数据结构,bfs,队列,搜索与图论,-,图中点的层次,数据结构,图)