欧拉路源自歌德七桥问题,一个点出发到达另一个,走过每一条边,出发点和终点相同称为欧拉回路
判断欧拉路,如果所有点联通,且入出度相同,或者仅有两个出入度相差为一则有欧拉路
欧拉回路出入度必须相同才成立
有向图最小欧拉路的求法
1 priority_queue<int>arr[N]; 2 int n, m; 3 int in[N]; 4 int out[N]; 5 int ans[N]; 6 int l = 0; 7 void dfs(int x) { 8 while (!arr[x].empty()) { 9 int x = -arr[x].top(); 10 arr[x].pop(); 11 dfs(x); 12 ans[++l] = x; 13 } 14 } 15 void euler() { 16 int x=0, y=0, z=0; 17 for (int i = 1; i <= n; ++i) { 18 if (in[i] != out[i]) 19 z++; 20 if (in[i] == out[i] - 1) 21 y++,x=i; 22 } 23 if (!(!z || (y == 1 && z == 2))) { 24 cout << "No" << endl; 25 return; 26 } 27 if (!x) { 28 for (int i = 1; i <= n; ++i) 29 { 30 if (in[i]) 31 { 32 x = i; 33 break; 34 } 35 } 36 } 37 dfs(x); 38 ans[++l] = x; 39 if (l != m + 1) {//判断所有的点是否联通 40 cout << "No" << endl; 41 return; 42 } 43 for (int i = l; i; --i) { 44 cout << ans[i] << ' '; 45 } 46 } 47 int main() { 48 cin >> n >> m; 49 for (int i = 0; i < m; ++i) { 50 int a, b; 51 cin >> a >> b; 52 arr[a].push(-b);//大根堆当小根堆用 53 out[a]++; 54 in[b]++; 55 } 56 euler(); 57 return 0; 58 }
无相图,可使用矩阵去标记两方向的边,这里用高级的异或去标记反向边
1 struct node { 2 int i; int dex;//i表示去往的点, 3 node(int i, int dex) { 4 this->i = i; 5 this->dex = dex; 6 } 7 bool operator<(const node& a)const { 8 return this->i > a.i; 9 } 10 }; 11 priority_queue<node>arr[N]; 12 int n, m; 13 int d[N]; 14 int ans[N]; 15 int l = 0; 16 int cnt = 1; 17 bool v[N]; 18 void dfs(int x) { 19 while (!arr[x].empty()) { 20 int to = arr[x].top().i; 21 int bian = arr[x].top().dex; 22 arr[x].pop(); 23 if (!v[bian]) { 24 v[bian] = v[bian ^ 1] = true;//反向边 25 ans[++l] = to; 26 dfs(to); 27 } 28 } 29 } 30 void euler() { 31 int x = 0, y = 0; 32 for (int i = n; i >= 1; --i) {//这里一定要从大到小,保证字典序最小 33 if (d[i] & 1) { 34 y++; 35 x = i; 36 } 37 } 38 if (y && y != 2) { 39 cout << "No" << endl; 40 return; 41 } 42 if (!x) { 43 for (int i = 1; i <= n; ++i) 44 { 45 if (d[i]) { 46 x = i; 47 break; 48 } 49 } 50 } 51 dfs(x); 52 ans[++l] = x; 53 if (l != m + 1) { 54 cout << "No" << endl; 55 return; 56 } 57 for (int i = l; i; --i) 58 cout << ans[i] << ' '; 59 } 60 int main() { 61 cin >> n >> m; 62 for (int i = 0; i < m; ++i) { 63 int a, b; 64 arr[b].push(node(a, ++cnt)); 65 arr[a].push(node(b, ++cnt)); 66 d[a]++; 67 d[b]++; 68 } 69 euler(); 70 return 0; 71 }
二分图,一般通过染色法,只有无向图才能二分图
1 int n, m; 2 vector<int>arr[N]; 3 int v[N]; 4 bool dfs(int x) { 5 for (int a : arr[x]) { 6 if (!v[a]) { 7 v[a] = 3 - v[x]; 8 if (!dfs(a)) 9 return false; 10 } 11 else if (v[a] == v[x]) 12 return false; 13 } 14 return true; 15 } 16 bool check() { 17 for (int i = 1; i <= n; ++i) { 18 if (!v[i]) { 19 v[i] = 1; 20 if (!dfs(i)) 21 return false; 22 } 23 } 24 return true; 25 } 26 int main() { 27 cin >> n >> m; 28 for (int i = 0; i < m; ++i) { 29 int a, b; 30 cin >> a >> b; 31 arr[a].push_back(b); 32 arr[b].push_back(a); 33 } 34 if (check()) 35 cout << "YES" << endl; 36 else 37 cout << "NO" << endl; 38 return 0; 39 }
浙公网安备 33010602011771号