算法竞赛进阶指南, 411页,欧拉回路(一笔画)
题目意思:
n个点,m条边的无向图,求一条路径,从1点出发,每条边(正反两个方向)都走一遍,
输出走的点的顺序。
本题要点:
1、使用邻接表来存图,每访问完一条边 (x, y), 及时修改表头 head[x], 使得它
指向吓一跳边。这样每次都取出 head[x], 自然就跳过了所有访问过的边。
2、用数组模拟栈(如果是系统栈,可能爆栈)。回溯过程中,弹栈,用 ans 数组来接,
然后数组 ans 存放的就是欧拉回路的所有点的顺序。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 10010, M = 100010;
int n, m, top, tot, cnt;
int head[N], ver[M], Next[M];
int s[M]; //模拟栈
int ans[M]; //答案栈
bool vis[M];
void add(int x, int y)
{
ver[++tot] = y, Next[tot] = head[x], head[x] = tot;
}
void euler()
{
s[++top] = 1;
while(top > 0)
{
int x = s[top], i = head[x];
//while(i && vis[i]) i = Next[i]; //找到一条尚未访问过的边
if(i)
{
s[++top] = ver[i];
//vis[i] = vis[i ^ 1] = true;
head[x] = Next[i];
}else{ //x连接的所有边都已经访问过了,回溯,级在答案栈中
top--;
ans[++cnt] = x;
}
}
}
int main()
{
scanf("%d%d", &n, &m);
tot = 1;
int x, y;
for(int i = 0; i < m; ++i)
{
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
}
euler();
for(int i = cnt; i; --i)
{
printf("%d\n", ans[i]);
}
return 0;
}
/*
4 5
1 2
1 4
2 3
2 4
3 4
*/
/*
1
2
3
4
2
1
4
3
2
4
1
*/