1. 程式人生 > >P2731 騎馬修柵欄 Riding the Fences(歐拉回路)

P2731 騎馬修柵欄 Riding the Fences(歐拉回路)

題目背景

Farmer John每年有很多柵欄要修理。他總是騎著馬穿過每一個柵欄並修復它破損的地方。

題目描述

John是一個與其他農民一樣懶的人。他討厭騎馬,因此從來不兩次經過一個柵欄。你必須編一個程式,讀入柵欄網路的描述,並計算出一條修柵欄的路徑,使每個柵欄都恰好被經過一次。John能從任何一個頂點(即兩個柵欄的交點)開始騎馬,在任意一個頂點結束。

每一個柵欄連線兩個頂點,頂點用1到500標號(雖然有的農場並沒有500個頂點)。一個頂點上可連線任意多(>=1)個柵欄。兩頂點間可能有多個柵欄。所有柵欄都是連通的(也就是你可以從任意一個柵欄到達另外的所有柵欄)。

你的程式必須輸出騎馬的路徑(用路上依次經過的頂點號碼錶示)。我們如果把輸出的路徑看成是一個500進位制的數,那麼當存在多組解的情況下,輸出500進製表示法中最小的一個 (也就是輸出第一位較小的,如果還有多組解,輸出第二位較小的,等等)。

輸入資料保證至少有一個解。

輸入輸出格式

輸入格式:

 

第1行: 一個整數F(1 <= F <= 1024),表示柵欄的數目

第2到F+1行: 每行兩個整數i, j(1 <= i,j <= 500)表示這條柵欄連線i與j號頂點。

 

輸出格式:

 

輸出應當有F+1行,每行一個整數,依次表示路徑經過的頂點號。注意資料可能有多組解,但是隻有上面題目要求的那一組解是認為正確的。

 

輸入輸出樣例

輸入樣例#1: 複製

9
1 2
2 3
3 4
4 2
4 5
2 5
5 6
5 7
4 6

輸出樣例#1: 複製

1
2
3
4
2
5
4
6
5
7

說明

題目翻譯來自NOCOW。

USACO Training Section 3.3

思路:歐拉回路的判斷,首先我們建立邊,以及度,然後我們開始找歐拉回路或者尤拉路徑,因為是無向圖,所以我們從輸入的最小的點開始找,找第一個度為奇數的點,如果存在就把這個點作為起點,那麼我們就會找到一條尤拉路徑,如果不存在,說明說有的度都是偶數,那麼存在歐拉回路,理論上我們從任意一點開始都可以,但是題目要求求序列最小的一組資料,所以我們以最小的點開始,找到這點後,我們開始用Hierholzer演算法來實現,最後輸出即可,餘下見程式碼

 

#include<iostream>
#include<stack>
using namespace std;
const int maxn = 510;
int n, a, b, st = 1e9, ed = 0;
int du[maxn], G[510][510];
stack<int> s;
void dfs(int u) {
    for (int i = st; i <= ed; i++) {
        if (G[u][i]) {
            G[u][i]--;
            G[i][u]--;
            dfs(i);
        }
    }
    s.push(u);
}
int main () {
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a >> b;
        st = min(a, min(b, st));
        ed = max(a, max(b, ed));
        G[a][b]++;
        G[b][a]++;
        du[a]++;
        du[b]++;
    }
    int x = st;
    for (int i = st; i <= ed; i ++) {
        if (du[i] & 1) {
            x = i;
            break;
        }
    }
    dfs(x);
    while (!s.empty()) {
        cout << s.top() << endl;
        s.pop();
    }
    return 0;
}