java版——用深度优先遍历广度优先遍历求最短路径

深度优先遍历

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int[] grade = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            grade[i] = cin.nextInt();
        }
        List<List<Integer>> edges = new ArrayList<>();
        for (int i = 0; i <= n; i++) {
            edges.add(new ArrayList<Integer>());
        }
        for (int i = 0; i < n - 1; i++) {
            int u = cin.nextInt();
            int v = cin.nextInt();
            // 双向边
            edges.get(u).add(v);
            edges.get(v).add(u);
        }
        int minDist = Integer.MAX_VALUE;
        for (int i = 1; i <= n; i++) {
            int currDist = dfs(edges, i, grade);
            if (currDist != -1) {
                minDist = Math.min(minDist, currDist);
            }
        }
        if (minDist == Integer.MAX_VALUE) {
            System.out.println(-1);
        } else {
            System.out.println(minDist);
        }
    }

	// 深度优先
    private static int dfs(List<List<Integer>> edges, int start, int[] grade) {
        int size = grade.length;
        boolean[] visited = new boolean[size];
        Deque<Integer> stack = new LinkedList<>();
        stack.push(start);
        visited[start] = true;
        int dist = 0;
        while (!stack.isEmpty()){
            // 这里先不要出栈,因为待会还要回来遍历它的其它孩子结点
            int u = stack.peek();
            if (u != start && grade[u] == grade[start]){
                return dist;
            }
            for(Integer v : edges.get(u)){
                if (!visited[v]){
                    stack.push(v);
                    visited[v] = true;
                    dist++;
                    break;
                }
            }
            // 栈顶结点和当前结点相同,说明上面循环没有找到它的孩子结点
            // 即该结点的所有孩子结点都已遍历过,则出栈
            if (stack.peek() == u){
                stack.pop();
                dist--;
            }
        }
        return -1;
    }
}

广度优先遍历

思想:用变量 currLevelNodeNum 存储当前层所有结点的个数,然后每出队一个结点, currLevelNodeNum 就减 1 ,当currLevelNodeNum == 0 时说明当前层的所有结点都已出队,则路径长度加一,并用 currLevelNodeNum 记录下一层的结点数,而下一层的结点数就为当前队列中的元素个数。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int[] grade = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            grade[i] = cin.nextInt();
        }
        List<List<Integer>> edges = new ArrayList<>();
        for (int i = 0; i <= n; i++) {
            edges.add(new ArrayList<Integer>());
        }
        for (int i = 0; i < n - 1; i++) {
            int u = cin.nextInt();
            int v = cin.nextInt();
            // 双向边
            edges.get(u).add(v);
            edges.get(v).add(u);
        }
        int minDist = Integer.MAX_VALUE;
        for (int i = 1; i <= n; i++) {
            int currDist = bfs(edges, i, grade);
            if (currDist != -1) {
                minDist = Math.min(minDist, currDist);
            }
        }
        if (minDist == Integer.MAX_VALUE) {
            System.out.println(-1);
        } else {
            System.out.println(minDist);
        }
    }

	// 广度优先
    private static int bfs(List<List<Integer>> edges, int start, int[] grade) {
        int size = grade.length;
        boolean[] visited = new boolean[size];
        Deque<Integer> queue = new LinkedList<>();
        queue.offer(start);
        visited[start] = true;
        int currLevelNodeNum = 1;
        // 路径长度
        int dist = 0;
        while (!queue.isEmpty()) {
            int u = queue.poll();
            currLevelNodeNum--;
            if (u != start && grade[u] == grade[start]) {
                return dist;
            }
            for (Integer v : edges.get(u)) {
                if (!visited[v]) {
                    queue.offer(v);
                    visited[v] = true;
                }
            }
            // 当前层所有结点都已出队
            if (currLevelNodeNum == 0) {
                currLevelNodeNum = queue.size();
                dist++;
            }
        }
        return -1;
    }
}