Skip to content

Commit b1e07e8

Browse files
authored
Update euler_path.md
1 parent 0da3b79 commit b1e07e8

File tree

1 file changed

+71
-67
lines changed

1 file changed

+71
-67
lines changed

src/graph/euler_path.md

Lines changed: 71 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -66,97 +66,101 @@ The program below searches for and outputs a Eulerian loop or path in a graph, o
6666

6767
First, the program checks the degree of vertices: if there are no vertices with an odd degree, then the graph has an Euler cycle, if there are $2$ vertices with an odd degree, then in the graph there is only an Euler path (but no Euler cycle), if there are more than $2$ such vertices, then in the graph there is no Euler cycle or Euler path.
6868
To find the Euler path (not a cycle), let's do this: if $V1$ and $V2$ are two vertices of odd degree, then just add an edge $(V1, V2)$, in the resulting graph we find the Euler cycle (it will obviously exist), and then remove the "fictitious" edge $(V1, V2)$ from the answer.
69-
We will look for the Euler cycle exactly as described above (non-recursive version), and at the same time at the end of this algorithm we will check whether the graph was connected or not (if the graph was not connected, then at the end of the algorithm some edges will remain in the graph, and in this case we need to print $-1$).
69+
We will look for the Euler cycle exactly as described above (recursive version), and at the same time at the end of this algorithm we will check whether the graph was connected or not (if the graph was not connected, then at the end of the algorithm some edges will remain in the graph, and in this case we need to print $-1$).
7070
Finally, the program takes into account that there can be isolated vertices in the graph.
7171

72-
Notice that we use an adjacency matrix in this problem.
73-
Also this implementation handles finding the next with brute-force, which requires to iterate over the complete row in the matrix over and over.
74-
A better way would be to store the graph as an adjacency list, and remove edges in $O(1)$ and mark the reversed edges in separate list.
75-
This way we can achieve an $O(N)$ algorithm.
76-
7772
```cpp
78-
int main() {
79-
int n;
80-
vector<vector<int>> g(n, vector<int>(n));
81-
// reading the graph in the adjacency matrix
82-
83-
vector<int> deg(n);
84-
for (int i = 0; i < n; ++i) {
85-
for (int j = 0; j < n; ++j)
86-
deg[i] += g[i][j];
87-
}
73+
vector<pair<int,int>> edges;
74+
vector<vector<int>> g;
75+
vector<bool> used;
76+
vector<int> res;
77+
78+
void add_edge(int u, int v) {
79+
int idx = (int) edges.size();
80+
edges.emplace_back(u, v);
81+
g[u].push_back(idx);
82+
g[v].push_back(idx);
83+
}
8884

89-
int first = 0;
90-
while (first < n && !deg[first])
91-
++first;
92-
if (first == n) {
93-
cout << -1;
94-
return 0;
85+
void dfs(int v) {
86+
while (!g[v].empty()) {
87+
int idx = g[v].back();
88+
g[v].pop_back();
89+
if (used[idx]) continue;
90+
used[idx] = true;
91+
auto [u, w] = edges[idx];
92+
dfs(u ^ w ^ v);
9593
}
94+
res.push_back(v);
95+
}
9696

97+
int main() {
98+
ios::sync_with_stdio(0);
99+
cin.tie(0);
100+
int n, m;
101+
cin >> n >> m;
102+
edges.clear();
103+
g.assign(n, vector<int> ());
104+
used.assign(m + 1, false);
105+
res.clear();
106+
for (int i = 0; i < m; i++) {
107+
int u, v;
108+
cin >> u >> v;
109+
u--, v--;
110+
add_edge(u, v);
111+
}
97112
int v1 = -1, v2 = -1;
98113
bool bad = false;
99-
for (int i = 0; i < n; ++i) {
100-
if (deg[i] & 1) {
101-
if (v1 == -1)
114+
for (int i = 0; i < n; i++) {
115+
if ((int) g[i].size() % 2) {
116+
if (v1 == -1) {
102117
v1 = i;
103-
else if (v2 == -1)
118+
} else if (v2 == -1) {
104119
v2 = i;
105-
else
120+
} else {
106121
bad = true;
122+
}
107123
}
108124
}
109-
110-
if (v1 != -1)
111-
++g[v1][v2], ++g[v2][v1];
112-
113-
stack<int> st;
114-
st.push(first);
115-
vector<int> res;
116-
while (!st.empty()) {
117-
int v = st.top();
118-
int i;
119-
for (i = 0; i < n; ++i)
120-
if (g[v][i])
121-
break;
122-
if (i == n) {
123-
res.push_back(v);
124-
st.pop();
125-
} else {
126-
--g[v][i];
127-
--g[i][v];
128-
st.push(i);
129-
}
125+
int first = 0;
126+
while (first < n && g[first].empty()) {
127+
first++;
128+
}
129+
if (bad || (v1 != -1 && v2 == -1) || first == n) {
130+
cout << -1 << '\n';
131+
return 0;
130132
}
131-
132133
if (v1 != -1) {
133-
for (size_t i = 0; i + 1 < res.size(); ++i) {
134+
add_edge(v1, v2);
135+
}
136+
dfs(first);
137+
if (v1 != -1) {
138+
for (int i = 0; i + 1 < (int) res.size(); i++) {
134139
if ((res[i] == v1 && res[i + 1] == v2) ||
135140
(res[i] == v2 && res[i + 1] == v1)) {
136-
vector<int> res2;
137-
for (size_t j = i + 1; j < res.size(); ++j)
138-
res2.push_back(res[j]);
139-
for (size_t j = 1; j <= i; ++j)
140-
res2.push_back(res[j]);
141-
res = res2;
141+
vector<int> nw;
142+
for (int j = i + 1; j < (int) res.size(); j++) {
143+
nw.push_back(res[j]);
144+
}
145+
for (int j = 1; j <= i; j++) {
146+
nw.push_back(res[j]);
147+
}
148+
res = nw;
142149
break;
143150
}
144151
}
145152
}
146-
147-
for (int i = 0; i < n; ++i) {
148-
for (int j = 0; j < n; ++j) {
149-
if (g[i][j])
150-
bad = true;
153+
for (int i = 0; i < n; i++) {
154+
if (!g[i].empty()) {
155+
cout << -1 << '\n';
156+
return 0;
151157
}
152158
}
153-
154-
if (bad) {
155-
cout << -1;
156-
} else {
157-
for (int x : res)
158-
cout << x << " ";
159+
for (int x : res) {
160+
cout << x + 1 << ' ';
159161
}
162+
cout << '\n';
163+
return 0;
160164
}
161165
```
162166
### Practice problems:

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy