算法 BISHI97旺仔哥哥走迷宫 思路 求解代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 public static void main(String[] args) throws IOException { // 使用 BufferedReader 和 PrintWriter 提升大规模数据下的 I/O 效率 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); // 读取第一行输入,获取节点数n和边数m String[] strA = br.readLine().trim().split("\\s+"); int n = Integer.parseInt(strA[0]); // 节点数量 int m = Integer.parseInt(strA[1]); // 边的数量 int[] t = new int[n + 1]; // 存储每个节点的类型,索引从1开始 // 读取第二行输入,获取每个节点的类型 String[] strB = br.readLine().trim().split("\\s+"); // 将节点类型数据存入数组t,索引从1开始 for (int i = 1; i <= n; i++) { t[i] = Integer.parseInt(strB[i - 1]); } // 创建邻接表表示的图结构 List<Integer>[] adj = new ArrayList[n + 1]; for (int i = 1; i <= n; i++) { adj[i] = new ArrayList<>(); } // 读取所有边的信息,构建无向图 for (int i = 0; i < m; i++) { String[] edge = br.readLine().trim().split("\\s+"); int u = Integer.parseInt(edge[0]); // 边的一个端点 int v = Integer.parseInt(edge[1]); // 边的另一个端点 adj[u].add(v); // 添加边到邻接表 adj[v].add(u); // 无向图,双向添加 } // 检查起点或终点是否为类型1,如果是则直接输出"No" if (t[1] == 1 || t[n] == 1) { out.println("No"); } else { // 调用BFS算法判断路径是否可行 if (bfs(n, adj, t)) { out.println("Yes"); } else { out.println("No"); } } // 刷新缓冲区确保数据完整写出并关闭流 out.flush(); out.close(); br.close(); } /** * 使用广度优先搜索(BFS)算法判断从节点1到节点n是否存在有效路径 * * @param n 节点总数 * @param adj 邻接表,表示图的连接关系 * @param t 数组,标记节点的状态(0表示可通过,非0表示不可通过) * @return 如果存在从节点1到节点n的有效路径则返回true,否则返回false */ private static boolean bfs(int n, List<Integer>[] adj, int[] t) { // 创建队列用于BFS遍历 Queue<Integer> queue = new LinkedList<>(); // 创建访问标记数组,记录节点是否被访问过 boolean[] visited = new boolean[n + 1]; // 从节点1开始搜索 queue.add(1); visited[1] = true; // 当队列不为空时,继续搜索 while (!queue.isEmpty()) { // 取出队首节点 int cur = queue.poll(); // 如果到达目标节点n,返回true if (cur == n) { return true; } // 遍历当前节点的所有邻接节点 for (int neighbor : adj[cur]) { // 如果邻接节点可通过且未被访问过 if (t[neighbor] == 0 && !visited[neighbor]) { // 标记为已访问并入队 visited[neighbor] = true; queue.add(neighbor); } } } // 队列已空未到达目标节点,返回false return false; }