【模板】歐拉回路/路徑和哈密爾頓迴路
阿新 • • 發佈:2022-04-08
尤拉路就是經過所有的邊恰好一次的路徑,歐拉回路就是轉轉完所有邊然後還要回到初始結點。
考慮歐拉回路即是所有結點出度等於入度。考慮尤拉路就是除了兩個結點,一個結點出-入==1,另一個入-出==1其他出度等於入度。
然後關於尤拉路的做法,按照離散數學就是找出一個環,然後把這個環上的所有邊去除掉然後再遞迴到各自的環上跑尤拉路。對於實現上來說,深搜可以做到這個,就是找出了一個環的同時,遞迴到各自下面的分支環上。做法就是搜到某個點,跑邊,然後刪除掉該邊,繼續跑,在跑完之後再將該點加入棧序列中。最終結果就是棧序列出棧的序列。
#include <bits/stdc++.h> using namespace std; const int maxn = 2e5 + 5; int n, m; vector<int> ve[maxn]; unordered_set<int> se[maxn]; int rd[maxn], cd[maxn]; int sta[maxn], top; int ded[maxn]; void dfs(int x) { for (int it = ded[x]; it < ve[x].size(); it = ded[x]) { ded[x] = it + 1; dfs(ve[x][it]); } sta[++top] = x; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); ve[x].push_back(y); cd[x]++, rd[y]++; } for (int i = 1; i <= n; i++) { sort(ve[i].begin(), ve[i].end()); } int qidian = 1; int c1 = 0, c2 = 0; bool huilu_flag = 1; for (int i = 1; i <= n; i++) { if (rd[i] != cd[i]) huilu_flag = 0; if (cd[i] - rd[i] == 1) c1++, qidian = i; if (rd[i] - cd[i] == 1) c2++; if (rd[i] - cd[i] >= 2 || cd[i] - rd[i] >= 2) { puts("No"); return 0; } } if ((!huilu_flag) && !(c1 == c2 && c1 == 1)) { puts("No"); return 0; } dfs(qidian); for (int i = top; i >= 1; i--) { printf("%d ", sta[i]); } }
關於哈密頓迴路
目前哈密頓迴路是一個NP問題,即可以最壞多項式時間複雜度判斷,但是目前是指數級別求。
我們可以通過狀態壓縮,解決這個問題。具體就是設定f[2^n][n]表示已經經過的點狀態+目前在的點。迴路就在求到經過恰好所有點一次後再分別判斷一下即可。如果沒有固定起點,那也就是O(2^n*n^2)解決的問題。總之,狀態壓縮是關鍵。