原题链接:
https://www.acwing.com/problem/content/1126/
就是说,一个图,无向图。有可能存在重边。
dfs为何使用那种顺序?
这个解释太棒了:
至于为什么最后才把这个点加到序列中,有以下的解释:
就是说存在一种可能,如果先加点,有可能dfs会直达终点,然后旁边的环还没有遍历。 所以说,我们需要先遍历当前点所有的相邻的点,然后最后把这个点加进去,然后逆序倒着输出。
然后题目中还要求,输出字典序最小的路经。下边这个解释也很棒。
代码:
/*
每两个点之间有一个栅栏,走一次就行,
只不过这个栅栏是双向的。
*/
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 510;
int n = 500, m;
int g[N][N]; // 使用临界矩阵存图
int ans[1100], cnt;
int d[N];
// u是顶点号。dfs必须在
void dfs(int u)
{
// 遍历u的所有可能的临边。按照编号从小到大的顺序
// 这样才会保证字典序最小
for(int i = 1; i <= n; i ++)
{
if(g[u][i])
{
// 删栅栏,双向边都要删掉
g[u][i] --, g[i][u] -- ;
dfs(i);
}
}
// 遍历完所有的临点,回溯的时候才加上自己
ans[ ++ cnt] = u;
}
int main()
{
cin >> m;
while(m -- )
{
int a, b;
cin >> a >> b;
g[a][b] ++, g[b][a] ++;
d[a] ++, d[b] ++; // 出度
}
// 找到一个出度不为0的点
int start = 1;
while (!d[start]) start ++ ;
// 找到一个出度为奇数的点。
for (int i = 1; i <= n; i ++ )
if (d[i] % 2)
{
start = i;
break;
}
dfs(start);
// 由于dfs的回溯,所以终点在最开始
for(int i = cnt; i; i -- ) printf("%d\n", ans[i]);
return 0;
}