图的遍历(Java/Py/C/C++/Js/Go)题解
华为OD机试真题 新系统 华为OD上机考试真题新系统 9月9号 100分题型
华为OD机试新系统真题目录点击查看: 华为OD机试新系统真题题库目录|机考题库 + 算法考点详解
题目内容
给定一个无向图,顶点编号从 1 1 1 到 n n n;从顶点 1 1 1 出发,进行深度优先搜索(DFS),当某个顶点有多个邻接点时,按照编号从小到大的顺序依次访问,输出遍历过程中访问顶点的顺序。
1 ≤ n ≤ 100 1 \le n \le 100 1≤n≤100, 0 ≤ m ≤ 100 0 \le m \le 100 0≤m≤100。若不连通,DFS 从顶点 1 1 1 出发无法遍历所有顶点,输出只包含可达顶点。输入保证没有自环如 ( i , i ) (i,i) (i,i),即顶点到自身的边;同时输入保证不会有多条相同的边,如 ( 1 , 2 ) (1,2) (1,2) 出现两次。
输入描述
- 整数 n n n, m m m:表示顶点数和边数;
- 二维数组
graph:每个元素有两个整数 u u u, v v v,表示 u u u 和 v v v 之间有一条无向边;
输出描述
- 数组:数组元素表示深度优先搜索访问顶点的顺序(从 1 1 1 开始);
样例1
输入
6 5
1 2
1 3
2 4
3 5
3 6
输出
1,2,4,3,5,6
说明
- 从 1 1 1 出发,邻接点有 { 2 , 3 } \{2,3\} {2,3},选小的 2 2 2
- 从 2 2 2 出发,邻接点有 { 1 , 4 } \{1,4\} {1,4}, 1 1 1 已访问,选 4 4 4
- 4 4 4 没有未访问邻接点,回溯到 2 2 2,回溯到 1 1 1,下一个未访问的是 3 3 3
- 从 3 3 3 出发,邻接点有 { 1 , 5 , 6 } \{1,5,6\} {1,5,6}, 1 1 1 已访问,选小的 5 5 5
- 5 5 5 没有未访问邻接点,回溯到 3 3 3,下一个未访问的是 6 6 6; 6 6 6 结束,遍历完成。最终访问顺序为 1 , 2 , 4 , 3 , 5 , 6 1,2,4,3,5,6 1,2,4,3,5,6。
样例2
输入
5 2
1 2
3 4
输出
1,2
说明
- 从 1 1 1 出发,邻接点有 { 2 } \{2\} {2},选 2 2 2
- 从 2 2 2 出发,邻接点有 { 1 } \{1\} {1}, 1 1 1 已访问,没有未访问邻接点,回溯到 1 1 1
- 1 1 1 没有其他未访问邻接点,遍历结束。顶点 3 3 3、 4 4 4、 5 5 5 与 1 1 1 不连通,无法到达,因此不输出。最终访问顺序为 1 , 2 1,2 1,2。
题解
思路:DFS
- 先利用给出的边,构造出联接矩阵
- 利用递归回溯从获取从1开始顶点访问顺序,主要注意下面几点:
- 防止重复访问,可以使用
vis布尔数组去重。 - 按照编号从小到大的顺序依次访问。可以按顺序选择与当前相邻顶点访问。
- 防止重复访问,可以使用
C++
cpp
#include <bits/stdc++.h>
#include <vector>
using namespace std;
// 递归访问
void dfs(int index, vector<bool>& vis, vector<int>& path, vector<vector<bool>>& edges) {
vis[index] = true;
path.push_back(index);
for (int i = 1; i < edges[index].size(); i++) {
if (!edges[index][i]) {
continue;
}
if (vis[i]) {
continue;
}
dfs(i, vis, path, edges);
}
}
vector<int> solve(int n, int m, vector<vector<int>>& graph) {
vector<int> ans;
// 联接矩阵
vector<vector<bool>> edges(n + 1, vector<bool>(n + 1, false));
for (int i = 0; i < m; i++) {
int u = graph[i][0];
int v = graph[i][1];
edges[u][v] = true;
edges[v][u] = true;
}
// 去重
vector<bool> vis(n + 1, false);
// 递归获取访问顺序
dfs(1, vis, ans, edges);
return ans;
}
int main() {
int n,m;
cin >> n >> m;
vector<vector<int>> graph(m);
for (int i = 0; i < m; i++) {
int u,v;
cin >> u >> v;
graph[i] = {u,v};
}
vector<int> ans = solve(n, m, graph);
for (int i = 0; i < ans.size(); i++) {
if (i > 0) {
cout << ",";
}
cout << ans[i];
}
return 0;
}
Java
java
import java.util.*;
public class Main {
// 递归访问
static void dfs(int index, boolean[] vis, ArrayList<Integer> path, boolean[][] edges) {
vis[index] = true;
path.add(index);
for (int i = 1; i < edges[index].length; i++) {
if (!edges[index][i]) {
continue;
}
if (vis[i]) {
continue;
}
dfs(i, vis, path, edges);
}
}
static ArrayList<Integer> solve(int n, int m, int[][] graph) {
ArrayList<Integer> ans = new ArrayList<>();
// 联接矩阵
boolean[][] edges = new boolean[n + 1][n + 1];
for (int i = 0; i < m; i++) {
int u = graph[i][0];
int v = graph[i][1];
edges[u][v] = true;
edges[v][u] = true;
}
// 去重
boolean[] vis = new boolean[n + 1];
// 递归获取访问顺序
dfs(1, vis, ans, edges);
return ans;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[][] graph = new int[m][2];
for (int i = 0; i < m; i++) {
int u = sc.nextInt();
int v = sc.nextInt();
graph[i][0] = u;
graph[i][1] = v;
}
ArrayList<Integer> ans = solve(n, m, graph);
for (int i = 0; i < ans.size(); i++) {
if (i > 0) {
System.out.print(",");
}
System.out.print(ans.get(i));
}
}
}
Python
python
# 递归访问
def dfs(index, vis, path, edges):
vis[index] = True
path.append(index)
for i in range(1, len(edges[index])):
if not edges[index][i]:
continue
if vis[i]:
continue
dfs(i, vis, path, edges)
def solve(n, m, graph):
ans = []
# 联接矩阵
edges = [[False] * (n + 1) for _ in range(n + 1)]
for i in range(m):
u = graph[i][0]
v = graph[i][1]
edges[u][v] = True
edges[v][u] = True
# 去重
vis = [False] * (n + 1)
# 递归获取访问顺序
dfs(1, vis, ans, edges)
return ans
n, m = map(int, input().split())
graph = []
for _ in range(m):
u, v = map(int, input().split())
graph.append([u, v])
ans = solve(n, m, graph)
print(",".join(map(str, ans)))
JavaScript
js
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const lines = [];
rl.on('line', (line) => {
lines.push(line);
});
rl.on('close', () => {
let index = 0;
const [n, m] = lines[index++].trim().split(/\s+/).map(Number);
const graph = new Array(m);
for (let i = 0; i < m; i++) {
const [u, v] = lines[index++].trim().split(/\s+/).map(Number);
graph[i] = [u, v];
}
// 递归访问
function dfs(index, vis, path, edges) {
vis[index] = true;
path.push(index);
for (let i = 1; i < edges[index].length; i++) {
if (!edges[index][i]) {
continue;
}
if (vis[i]) {
continue;
}
dfs(i, vis, path, edges);
}
}
function solve(n, m, graph) {
const ans = [];
// 联接矩阵
const edges = Array.from(
{ length: n + 1 },
() => new Array(n + 1).fill(false)
);
for (let i = 0; i < m; i++) {
const u = graph[i][0];
const v = graph[i][1];
edges[u][v] = true;
edges[v][u] = true;
}
// 去重
const vis = new Array(n + 1).fill(false);
// 递归获取访问顺序
dfs(1, vis, ans, edges);
return ans;
}
const ans = solve(n, m, graph);
console.log(ans.join(','));
});
Go
go
package main
import (
"bufio"
"fmt"
"os"
)
// 递归访问
func dfs(index int, vis []bool, path *[]int, edges [][]bool) {
vis[index] = true
*path = append(*path, index)
for i := 1; i < len(edges[index]); i++ {
if !edges[index][i] {
continue
}
if vis[i] {
continue
}
dfs(i, vis, path, edges)
}
}
func solve(n int, m int, graph [][]int) []int {
ans := []int{}
// 联接矩阵
edges := make([][]bool, n+1)
for i := 0; i <= n; i++ {
edges[i] = make([]bool, n+1)
}
for i := 0; i < m; i++ {
u := graph[i][0]
v := graph[i][1]
edges[u][v] = true
edges[v][u] = true
}
// 去重
vis := make([]bool, n+1)
// 递归获取访问顺序
dfs(1, vis, &ans, edges)
return ans
}
func main() {
in := bufio.NewReader(os.Stdin)
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
var n, m int
fmt.Fscan(in, &n, &m)
graph := make([][]int, m)
for i := 0; i < m; i++ {
var u, v int
fmt.Fscan(in, &u, &v)
graph[i] = []int{u, v}
}
ans := solve(n, m, graph)
for i := 0; i < len(ans); i++ {
if i > 0 {
fmt.Fprint(out, ",")
}
fmt.Fprint(out, ans[i])
}
}
C语言
cpp
#include <stdio.h>
#include <stdlib.h>
// 递归访问
void dfs(int index, int *vis, int *path, int *pathSize, int **edges, int n) {
vis[index] = 1;
path[(*pathSize)++] = index;
for (int i = 1; i <= n; i++) {
if (!edges[index][i]) {
continue;
}
if (vis[i]) {
continue;
}
dfs(i, vis, path, pathSize, edges, n);
}
}
int *solve(int n, int m, int **graph, int *ansSize) {
// 联接矩阵
int **edges = (int **)malloc((n + 1) * sizeof(int *));
for (int i = 0; i <= n; i++) {
edges[i] = (int *)calloc(n + 1, sizeof(int));
}
for (int i = 0; i < m; i++) {
int u = graph[i][0];
int v = graph[i][1];
edges[u][v] = 1;
edges[v][u] = 1;
}
// 去重
int *vis = (int *)calloc(n + 1, sizeof(int));
int *ans = (int *)malloc((n + 1) * sizeof(int));
*ansSize = 0;
// 递归获取访问顺序
dfs(1, vis, ans, ansSize, edges, n);
free(vis);
for (int i = 0; i <= n; i++) {
free(edges[i]);
}
free(edges);
return ans;
}
int main() {
int n, m;
scanf("%d %d", &n, &m);
int **graph = (int **)malloc(m * sizeof(int *));
for (int i = 0; i < m; i++) {
int u, v;
scanf("%d %d", &u, &v);
graph[i] = (int *)malloc(2 * sizeof(int));
graph[i][0] = u;
graph[i][1] = v;
}
int ansSize = 0;
int *ans = solve(n, m, graph, &ansSize);
for (int i = 0; i < ansSize; i++) {
if (i > 0) {
printf(",");
}
printf("%d", ans[i]);
}
free(ans);
for (int i = 0; i < m; i++) {
free(graph[i]);
}
free(graph);
return 0;
}