赞
踩
输入格式
输入第一行给出三个正整数,分别表示地下迷宫的节点数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; } } }
看了其他的贴子,感觉我这种方法算是比较好懂的吧,哈哈哈哈哈哈(多多指教!)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。