-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathcaminhoeuleriano.cpp
More file actions
118 lines (114 loc) · 2.8 KB
/
caminhoeuleriano.cpp
File metadata and controls
118 lines (114 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <bits/stdc++.h>
using namespace std;
#define int long long int
#define pb push_back
#define pi pair<int, int>
#define pii pair<int, pi>
#define fir first
#define sec second
#define MAXN 200005
#define mod 998244353
struct euler_tour
{
int n, m, odd;
vector<vector<pi>> adj;
vector<int> path;
vector<bool> vis;
euler_tour(int _n, vector<pi> &edges) // recebe um grafo undirected, numero de vertices e as arestas
{
n = _n;
m = edges.size();
path.clear();
adj.resize(n);
vis.assign(m, false);
for (int i = 0; i < m; i++)
{
adj[edges[i].fir].pb({edges[i].sec, i});
adj[edges[i].sec].pb({edges[i].fir, i});
}
odd = 0;
for (int i = 0; i < n; i++)
{
odd += (adj[i].size() % 2);
}
}
void dfs(int s)
{
while (adj[s].size() > 0)
{
auto v = adj[s].back();
adj[s].pop_back();
if (!vis[v.sec])
{
vis[v.sec] = 1;
dfs(v.fir);
}
}
path.pb(s);
}
pair<bool, vector<int>> find_cycle(int source) // ve se tem caminho ciclo começando em source e terminando nele mesmo
{
if (odd != 0)
return {false, {}};
dfs(source);
if (path.size() != (m + 1) || path[0] != source || path.back() != source)
return {false, {}};
return {true, path};
}
pair<bool, vector<int>> find_path(int source, int dest) // ve se tem caminho euleriano de source ate dest
{
if (odd != 2)
return {false, {}};
if (adj[source].size() % 2 == 0 || adj[dest].size() % 2 == 0)
return {false, {}};
dfs(source);
reverse(path.begin(), path.end());
if (path.size() != (m + 1) || path[0] != source || path.back() != dest)
return {false, {}};
return {true, path};
}
pair<bool, vector<int>> find_euler(int source, int dest)
{
if (source == dest)
return find_cycle(source);
return find_path(source, dest);
}
};
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, m;
cin >> n >> m;
vector<pi> edges(m);
for (int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
a--, b--;
edges[i] = {a, b};
}
euler_tour et(n, edges);
auto [exists, path] = et.find_euler(0, 0);
if (exists)
{
for (auto const &i : path)
cout << i + 1 << " ";
cout << endl;
}
else
{
cout << "IMPOSSIBLE\n";
}
return 0;
}
// caminho euleriano em um grafo
// passa por todas as arestas apenas uma unica vez e percorre todas elas
// condição de existencia:
// todos os vértices possuem grau par (ciclo euleriano) começa e acaba no mesmo vértice
// ou
// apenas 2 vértices possuem grau impar, todos os outros possuem grau par ou == 0.
// começa num vertice de grau impar e termina num vértice de grau impar nesse caso.
// testado em:
// https://cses.fi/problemset/task/1691/
// https://codeforces.com/gym/106178/problem/A