題目大意
無向連通圖,求歐拉路徑。
樣例輸入&輸出
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;
}