1. 程式人生 > >【JZOJ 1319】 郵遞員

【JZOJ 1319】 郵遞員

Description

無向圖中,求一個字典序最小的歐拉回路

Analysis

不考慮字典序,歐拉回路如何求?
大致思想:
1.找到一條迴路
2.由於是dfs,走的順序剛好與退棧的順序相反
3.在退棧的過程中,可能迴路中某個點有另一條迴路要走,再次dfs進去
4.dfs完之後,把小歐拉回路剛好拼接(插入)在大歐拉回路中
5.重複執行3,直到所有邊都走過
考慮字典序只需要我們在dfs遍歷的時候先走編號小的點

演算法經過每條邊一次,為O(m)級別

Code

實現巧妙運用了一個棧,極大簡化程式碼

#include <ctime>
#include <cstdio>
#include <cstring> #include <algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) #define efo(i,v) for(int i=last[v];i;i=next[i]) using namespace std; typedef long long ll; const int N=205; int n,m,a[N][N],sta[N*N]; void read(int &t) { t=0
;char ch; for(ch=getchar();ch<'0' || ch>'9';ch=getchar()); for(;'0'<=ch && ch<='9';ch=getchar()) t=t*10+ch-'0'; } void dfs(int v) { fo(i,1,n) if(a[v][i]) { a[v][i]--,a[i][v]--; dfs(i); } sta[++sta[0]]=v; } int main() { int
x,y; read(n),read(m); fo(i,1,n) read(x); fo(i,1,m) { read(x),read(y); a[x][y]++,a[y][x]++; } dfs(1); printf("%d\n",sta[0]-1); while(sta[0]) printf("%d ",sta[sta[0]--]); return 0; }