题目传送门
题目大意
给定一个 n n n 个点的无向图,从根节点 1 1 1 开始,按照以下遍历规则遍历:
-
如果这个点所能到达的点中有没有遍历过的,那么就按照编号的从小到大的顺序遍历。
-
否则,那么:
- 如果此点为 1 1 1,结束遍历。
- 否则回溯到上一点。
请你按照遍历顺序输出到达过的点的编号。
解题思路
我们肯定得存储这个无向图对吧,于是就用到了 vector
容器。题目要求按照编号的递增顺序进行遍历对吧,所以就把每个节点的子节点都给 sort
排下序。题目说如果这个点的子节点中有没被遍历过的就遍历,都遍历过了就回溯对吧,所以我们直接 dfs
爆搜,输出一下当前节点的编号,遍历子节点,打标记,然后我们就会惊奇地发现这题居然如此简单。
如果不会建图的话,我就讲一下(会的神犇可以跳过)。
首先 vector
可以理解为一个动态数组,而 vector<int> a[200010]
就是定义一个二维数组,a[1].push_back(2)
就是将 2 2 2 添加在了编号为 1 1 1 的序列中,因此我们使用 vector
建图的时候,a[1].push_back(2)
就可以理解为 1 1 1 与 2 2 2 之间创建了一条边 1 → 2 1\to2 1→2,而 a[1].push_back(2),a[2].push_back(1)
就可以理解为创建了两条边 1 → 2 , 2 → 1 1\to2,2\to1 1→2,2→1,这就是无向图的创建。
CODE:
#include <bits/stdc++.h>
using namespace std;
vector<int> a[200010];
bool vis[200010];
void dfs(int now) {
cout << now << ' ';
vis[now] = true;
for (int i = 0; i < a[now].size(); i++)
if (!vis[a[now][i]])
dfs(a[now][i]), cout << now << ' ';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
a[u].push_back(v);
a[v].push_back(u);
}
for (int i = 1; i <= n; i++)
sort(a[i].begin(), a[i].end());
dfs(1);
return 0;
}
总结
这道题目没有什么难点,只要我们跟着题目的思路走,就可以轻松写完代码。