AcWing 1124. 騎馬修柵欄
阿新 • • 發佈:2022-04-07
- 本題資料量較小,可以使用鄰接矩陣
- 要求輸出最小字典序,我們需要保證由小點出發,一路上從小列舉到大
- 考查無向圖求尤拉路徑的辦法
一、鄰接矩陣模板
#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; }