-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCiclo_Euleriano.cpp
More file actions
193 lines (148 loc) · 6.85 KB
/
Ciclo_Euleriano.cpp
File metadata and controls
193 lines (148 loc) · 6.85 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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*
@ Docente:
* Joao Patricio.
@ Estudante:
* Joao Victor do Rozario Recla.
@ Disciplina:
* Analise e Sintese de Algoritmos.
@ Instituicao:
* IPT - Instituto Politecnico de Tomar.
* ESTA - Escola Superior de Tecnologia de Abrantes.
Este arquivo contem a implementacao dos metodos necessarios
para verificar se um grafo eh euleriano e encontrar um tour
de euler em um grafo euleriano.
*/
#include "Grafos.cpp"
/* Classe de algoritmos para resolver os
problemas que envolvem ciclos eulerianos. */
class Ciclo_Euleriano {
private: ll K; // Quantidade de vertices no 'subgrafo de euler' do grafo 'G'.
private: ll Raiz; // Indicador do vertice de partida do tour.
public: Grafos *G; // G: Representacao computacional de um grafo.
private: ll Ponte_v; // Indicador de que um vertice 'V' eh extremidade de uma ponte.
private: ll Ponte_w; // Indicador de que um vertice 'W' eh extremidade de uma ponte.
private: vector<ll> Tour; // Vetor de vertices que representam o 'Tour de Euler' no grafo.
/* Construtor da classe. */
//============================
public: Ciclo_Euleriano(Grafos *G, ll Inicio = 0){
this->G = G;
this->K = G->QV;
this->Ponte_v = -1;
this->Ponte_w = -1;
this->Raiz = Inicio;
this->Tour.push_back(Inicio); // Vertice raiz do tour.
}
/* Metodo para verificar se todos
os vertices do grafo sao pares.
(CONDICAO PARA UM GRAFO SER EULERIANO) */
//============================================
public: bool Verificar_Graus_Pares_(){
ll i = this->G->QV;
bool Vertices_Pares = true; // Indica que o grafo eh euleriano (inicialmente).
while(--i > -1){
// Verifica se algum vertice tem grau impar.
if((this->G->Vert[i].Grau % 2) != 0){
Vertices_Pares = false; // Indica que o grafo nao eh euleriano (conclusao).
break;
}
}
return Vertices_Pares;
}
/* Metodo para realizar o percurso
em profundidade no grafo. */
//=================================
void Percurso_Profundidade_(ll V, ll &Alc, vector<ll> &Alcancados){
Alcancados[V] = ++Alc; // Indica que o vertice foi alcancados.
// Loop: Percorre a lista de adjacencia de V.
for(auto& W: this->G->Vert[V].Adj){
// Verifica se o vertice W nao foi alcancado.
if(Alcancados[W] == 0){
/* PONTES:
Uma aresta (V, W), ou (W, V), é ignorada no percurso
em profundidade caso esteja indicada, como possivel
ponte, nas variaveis 'Ponte_v' e 'Ponte_w'. */
//========================================================
if(!(((Ponte_v == V) && (Ponte_w == W)) || ((Ponte_v == W) && (Ponte_w == V))))
Percurso_Profundidade_(this->G->Vert[W].No, Alc, Alcancados); // Explora o grafo em profundidade.
}
}
}
/* Metodo para verificar se o grafo eh
conexo usando percurso em profundidade.
(CONDICAO PARA UM GRAFO SER EULERIANO) */
//============================================
public: bool Verificar_Grafo_Conexo_(){
ll Alc = 0; // Numero de vertices alcancados.
vector<ll> Alcancados(this->G->QV, 0); // Vetor para indicar se um vertice ja foi alcancado.
this->Percurso_Profundidade_(this->G->Vert[Raiz].No, Alc, Alcancados);
/* Verifica se todos os vertices, no
subgrafo de euler, foram alcancados. */
//============================================
if(Alc != this->K) return false; // Desconexo.
return true; // Conexo.
}
/* Metodo para verificar se uma aresta
(V, W), do grafo, eh uma ponte. */
//=====================================
bool Verificar_Ponte_(int V, int W){
/* PONTES:
Indicacao das extremidades de uma possivel ponte.
A aresta (V, W) passa a ser ignorada no percurso
em profundidade para verificar se o subgrafo de
de euler continua conexo sem a aresta. */
//===================================================
this->Ponte_v = V;
this->Ponte_w = W;
// Verifica se o grafo se torna desconexo.
if(Verificar_Grafo_Conexo_() == false) return true; // A aresta eh realmente uma ponte.
return false; // A aresta nao eh uma ponte.
}
/* Metodo para encontrar um tour
de euler em um grafo euleriano. */
//====================================
public: void Tour_Euler___FLEURY_(){
ll V, W; // Extremidades de uma aresta.
set<ll> *Arestas; // Lista de adjacencia auxiliar.
// Loop: Enquanto houver arestas no grafo.
while(this->G->QE != 0){
V = Tour.back(); // ESCOLHA DE UM VERTICE: Ultimo vertice alcancado no tour.
Arestas = &(this->G->Vert[V].Adj); // ESCOLHA DAS ARESTAS (V, W): Lista de arestas para iniciar o tour.
// Loop: Percorre a lista de adjacencia de V.
for(auto& auxW: (*Arestas)){
/* A aresta (V, W) eh escolhida se existe
apenas ela, ou se (V, W) nao eh ponte. */
if(((*Arestas).upper_bound(auxW) == (*Arestas).end())
|| (Verificar_Ponte_(V, auxW) == false)){
W = auxW;
break;
}
}
// Remocao da aresta (V, W) do subgrafo.
//===========================================
this->G->Remover_Aresta_(V, W); // Remove a aresta (V, W) de G.
this->G->Remover_Aresta_(W, V); // Remove a aresta (W, V) de G.
this->Tour.push_back(W); // Insere a aresta (V, W) no Tour.
/* Verifica se V nao possui mais vertices
adjacentes apos a remocao da aresta (V, W). */
if((this->G->Vert[V].Grau == 0))
this->K--; // Nesse caso atualiza-se o numero de vertices no subgrafo de euler do grafo G.
}
}
/* Metodo para imprimir o
tour de euler encontrado. */
//================================
public: void Imprimir_Tour_Euler_(){
cout << endl;
cout << "|-| ============== |-|" << endl;
cout << "|-| TOUR DE EULER: ";
for(auto& Vert: this->Tour)
cout << " " << Vert +1;
cout << "\n|-| ============== |-|" << endl;
}
/* Destructor da classe. */
//============================
public: ~Ciclo_Euleriano(){
this->Tour.clear();
delete(this->G);
}
};