题目大意
无向连通图,求欧拉路径。
样例输入&输出
sample input
一个m,道路数,m对数,路的两个端点。
9
1 2 2 3 3 4 4 2 4 5 2 5 5 6 5 7 4 6
sample output
字典序走的路径
1 2 3 4 2 5 4 6 5 7
分析&反思
一开始大陆暴力dfs,4个点。后来了解到了新算法 fleury 佛罗莱算法。
目前还不大理解,但模板挺好背的。
先复习一下欧拉路径和欧拉回路。
欧拉路径:不重复走边,走完所有的边。
条件:度数为奇的点小于2,必从奇点出发,或必回到奇点。若有向图则是入读比出度大1和入度比出度大1的两个点。
欧拉回路:不重复走边,走完所有的边,且回到出发点。
条件:无奇点。
此外,如果没有奇点,从任意点出发都可以得到解。
fleury算法就是。。。建立一个栈,先把起点放进去,开始循环。取栈顶弹出,如果无路可走(路都被走过了),就加入答案序列。若有路可走,dfs这个点,一路走并标记路,将走过的点加入栈,直到走不动(根据我的理解。。。dfs后可以得到一个桥对面的连通块)。
算了我还是以后理解了再补吧。
代码
/*
ID:changsz1
LANG:C++
TASK:fence
*/
#include<cstdio>
#include<iostream>
using namespace std;
const int maxn = 503;
int n1 = 1000000000, n2, m, map[maxn][maxn], du[maxn];
int ans[maxn*3], cnt;
int stack[maxn*3], top;
void dfs(int x) {
stack[++top] = x;
for(int i = n1; i <= n2; i++) {
if(map[x][i]) {
map[x][i]--;
map[i][x]--;
dfs(i);
break;
}
}
return;
}
void fleury(int u) {
int flag = 0;
stack[++top] = u;
while(top) {
flag = 0;
u = stack[top--];
for(int v = n1; v <= n2; v++) {
if(map[u][v]) {
flag = 1;
break;
}
}
if(flag) dfs(u);
else ans[++cnt] = u;
}
}
int main() {
freopen("fence.in", "r", stdin);
freopen("fence.out", "w", stdout);
scanf("%d", &m);
for(int i = 1, u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
map[u][v]++;
map[v][u]++;//存在重边
n1 = min(n1, min(u, v));
n2 = max(n2, max(v, u));
du[v]++;
du[u]++;
}
int ji = 0;
for(int i = n1; i <= n2; i++) if(du[i]%2 == 1) ji++;
if(!ji) fleury(n1);
else for(int i = n1; i <= n2; i++) if(du[i]%2 == 1) fleury(i);
for(int i = m+1; i; i--) printf("%d\n", ans[i]);
return 0;
}