1. 程式人生 > 其它 >AcWing 1124. 騎馬修柵欄

AcWing 1124. 騎馬修柵欄

題目傳送門

  • 本題資料量較小,可以使用鄰接矩陣
  • 要求輸出最小字典序,我們需要保證由小點出發,一路上從小列舉到大
  • 考查無向圖求尤拉路徑的辦法

一、鄰接矩陣模板

#include <bits/stdc++.h>
using namespace std;

const int N = 510;

int n = 500, m;
int g[N][N];      //鄰接矩陣
vector<int> path; //尤拉路徑
int d[N];         //度數
void dfs(int u) {
    //我們在遍歷的時候,把走過的路刪掉,這樣就不會重複走了,而且省去了反覆橫跳的風險
    for (int i = 1; i <= n; i++)  //列舉每個點
        if (g[u][i]) {            //如果u->i存在一條邊
            g[u][i]--, g[i][u]--; //那麼我們刪除掉正向邊和反向邊
            dfs(i);               //繼續搜尋
        }
    path.push_back(u); //記錄這個點
}

int main() {
    cin >> m;
    while (m--) {
        int a, b;
        cin >> a >> b;
        g[a][b]++, g[b][a]++; //鄰接矩陣記錄無向邊
        d[a]++, d[b]++;       //記錄無向圖的度數
    }

    //下面這樣去費勁找到第一個可行的度數為奇數的點,是為了最小字典序
    //較小編號作為起點
    int start = 1;               //預設從1號點出發
    while (!d[start]) start++;   //如果是孤立點,那麼繼續嘗試其它點
    for (int i = 1; i <= n; i++) //嘗試找到度數為奇數的點
        if (d[i] % 2) {
            start = i;
            break;
        }
    //無向圖開始查詢尤拉路徑
    dfs(start);
    //輸出尤拉路徑
    for (int i = path.size() - 1; i >= 0; i--) printf("%d\n", path[i]);
    return 0;
}

二、鄰接表解法

#include <bits/stdc++.h>
using namespace std;

const int N = 5e3 + 10;
typedef pair<int, int> PII;
int n = 500, m;
vector<int> path;
bool st[N];
int d[N];
int h[N], e[N], ne[N], idx;
void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u) {
    vector<PII> a;
    for (int i = h[u]; ~i; i = ne[i]) a.push_back({e[i], i});
    sort(a.begin(), a.end()); //從小到大排序
    for (int i = 0; i < a.size(); i++) {
        int edge = a[i].second;
        if (st[edge] || st[edge ^ 1]) continue;
        st[edge] = st[edge ^ 1] = true;
        dfs(a[i].first);
    }
    path.push_back(u);
}
int main() {
    memset(h, -1, sizeof h);
    cin >> m;
    while (m--) {
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a);
        d[a]++, d[b]++;
    }

    int start = 1;
    while (!d[start]) start++;
    for (int i = 1; i <= n; i++)
        if (d[i] & 1) {
            start = i;
            break;
        }
    dfs(start);
    for (int i = path.size() - 1; i >= 0; i--) cout << path[i] << endl;
    return 0;
}