1. 程式人生 > >計蒜客--農場看守(簡單的歐拉回路)

計蒜客--農場看守(簡單的歐拉回路)

蒜頭君最近做了農場看守,他每天晚上的工作就是巡視農場並且保證沒有人破壞農場。從穀倉出發去巡視,並且最終回到穀倉。

蒜頭君視力不太好,其他農場守衛只需要對農場的每一條連線不同場地的路走一遍就可以發現是不是有異常情況了。但是他很仔細和耐心,對農場的每一條連線不同場地的路需要走兩遍,並且這兩遍必須是不同的方向,因為他覺得應該不會兩次都忽略農場中的異常情況。

每兩塊地之間一定至少有一條路連線。現在的任務就是幫他制定巡視路徑。

輸入格式

第一行輸入兩個整數N(2 ≤ N ≤ 10000)N(2≤N≤10000)M(1≤ M ≤ 50000)M(1≤M≤50000),表示農場一共有N塊地M條邊。

第二到M+1行輸入兩個整數,表示對應的兩塊地之間有一條邊。

輸出格式

輸出2M+1個數,一個數佔一行,表示蒜頭君巡查路徑上地的標號,1 號為穀倉,從 1 開始,以 1 結束。如果有多種答案,輸出任意一種。

本題答案不唯一,符合要求的答案均正確

樣例輸入

4 5

1 2

1 4

2 3

2 4

3 4

樣例輸出

1

2

3

4

2

1

4

3

2

4

1

一開始看,想到的是設定一個vis[a][b]的陣列,從頭開始走,只要vis[a][b]是false就可以去訪問,讓陣列內元素都為真便實現了全部訪問兩邊。但是無法實現從1出發再回到1。看了老師的題解後知道了這是簡單的歐拉回路。題解如下。注意cout一定要在dfs函式之後因為實際程式的訪問順序是 先把和1有關的全訪問了然後返回再訪問其他的,第一次執行到底返回就輸出了1,然後最後一次返回輸出另一個1。

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
int n,m;
struct Edge{
   int v;
   bool vis;
   Edge(){}
   Edge(int v,bool vis):v(v),vis(vis){}
}edges[20020];//要記得開的大一些否則會出現答案錯誤。
vector<Edge>G[50010];
void euler(int u){//euler函式的主體,cout一定要放在函式最後!!
   // cout<<u<<endl;
   for(int i=0;i<G[u].size();i++){
       Edge &e=G[u][i];
       if(!e.vis){
           e.vis=true;
           euler(e.v);
          // cout<<u<<endl;
       }
    }
    cout<<u<<endl;
}
int main(){
   cin>>n>>m;
   for(int i=0;i<m;i++){
       int u,v;
       cin>>u>>v;//讀取邊數;
       G[u].push_back(Edge(v,false));
       G[v].push_back(Edge(u,false));
    }
   euler(1);
   return 0;
}