输入格式
输入第一行给出三个正整数,分别表示地下迷宫的节点数N(1<N≤1000,表示通道所有交叉点和端点)、边数M(≤3000,表示通道数)和探索起始节点编号S(节点从1到N编号)。随后的M行对应M条边(通道),每行给出一对正整数,分别是该条边直接连通的两个节点的编号。
输出格式
若可以点亮所有节点的灯,则输出从S开始并以S结束的包含所有节点的序列,序列中相邻的节点一定有边(通道);否则虽然不能点亮所有节点的灯,但还是输出点亮部分灯的节点序列,最后输出0,此时表示迷宫不是连通图。
由于深度优先遍历的节点序列是不唯一的,为了使得输出具有唯一的结果,我们约定以节点小编号优先的次序访问(点灯)。在点亮所有可以点亮的灯后,以原路返回的方式回到起点。
输入样例
6 8 1
1 2
2 3
3 4
4 5
5 6
6 4
3 6
1 5
输出样例
1 2 3 4 5 6 5 4 3 2 1
重新复述题目一遍就是:深度优先遍历一张图(只遍历包含起点的连通分量),若无法继续继续深度优先遍历,则退回上一个结点看是否能继续深度遍历的问题。若无法遍历所有顶点,生成路线后输出一个0.
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
int m, n, start; //start 为起点
vector<bool> visited;
vector<vector<int> > v;
stack<int> s;
//代码精髓
void dfs(int root)
{
visited[root] = 1;
//题目要求从编号小的优先遍历 我就排序了一遍
sort(v[root].begin(), v[root].end());
for (int i = 0; i < v[root].size(); i++)
{
//如果存在能继续遍历的点
if (!visited[v[root][i]])
{
s.push(root);
//将前一个点入栈
printf("%d ", v[root][i]);
//输出下一个点
dfs(v[root][i]);
//从下一个点开始继续深度优先遍历
}
}
//如果这个点没有能继续深度优先遍历的点
if (root != start)
{
//输出前一个点
printf("%d ", s.top());
//跳出这次递归
s.pop();
}
}
int main()
{
cin >> m >> n >> start;
v.resize(m+1);
visited.resize(m + 1, 0 );
for (int i = 1; i <= n; i++)
{
int a, b;
cin >> a >> b;
v[a].push_back(b);
v[b].push_back(a);
}
//构建邻接表
printf("%d ", start);
//先输出起点
dfs(start);
for (int i = 1; i <= m; i++)
{
if (!visited[i])
{
cout << 0;
break;
}
}
}
看了其他的贴子,感觉我这种方法算是比较好懂的吧,哈哈哈哈哈哈(多多指教!)