-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSem7_Euler.py
197 lines (164 loc) · 5.77 KB
/
Sem7_Euler.py
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
194
195
196
197
## Versão Univesp
"""
Caminho de Euler
"""
from random import randint
def gera_matriz(n):
"""
Gera uma matriz booleana aleatória nₓn
:param n: Tamanho do grafo (quantidade de vértices ou nós)
:return: Matriz de tamanho n
"""
geralLista = lambda x: [randint(0, 1) for i in range(x)]
matriz = []
for l in range(n):
matriz.append(geralLista(n))
return matriz
def iseuler(matrix):
"""
Verifica se o grafo apresensenta caminho de Euler
:param matrix: Matriz de adjacência do grafo
:return: True/False para existência ou não de caminho de Euler
"""
# Obtem a quantidade de nós do grafo:
n = len(matrix)
# Verifica se a matriz é válida
qtdeNosImpares = 0
if type(matrix) == list and len(matrix[0]) == n:
for i in matrix:
qtdeNosImpares += sum(i) % 2
if qtdeNosImpares == 3:
break
else:
return False
return (qtdeNosImpares <= 2)
print('\n', str('>>> Matriz Aleatória <<<').center(80, '-'))
m = gera_matriz(randint(3, 20))
print('\nMatriz de adjacência: ', m)
print('Existe um caminho de Euler? ', iseuler(m))
print('\n', str('>>> Fim do programa iseuler <<<').center(80, '-'))
print('\n', str('>>> Matriz 5x5 conexa e SEM arcos paralelos com solução <<<').center(80, '-'))
m = [[0, 1, 1, 0, 1],
[1, 0, 0, 1, 0],
[1, 0, 0, 1, 0],
[0, 1, 1, 0, 1],
[1, 0, 0, 1, 0]]
print('\nMatriz de adjacência: ', m)
print('Existe um caminho de Euler? ', iseuler(m))
print('\n', str('>>> Matriz 5x5 conexa e COM arcos paralelos SEM solução <<<').center(80, '-'))
m = [[0, 2, 1, 0, 0],
[2, 0, 1, 0, 0],
[1, 1, 0, 1, 1],
[0, 0, 1, 0, 2],
[0, 0, 1, 2, 0]]
print('\nMatriz de adjacência: ', m)
print('Existe um caminho de Euler? ', iseuler(m))
print('\n', str('>>> Fim do programa iseuler <<<').center(80, '-'))
## Versão: https://www.geeksforgeeks.org/fleurys-algorithm-for-printing-eulerian-path/
# Python program print Eulerian Trail in a given Eulerian or Semi-Eulerian Graph
from collections import defaultdict
# This class represents an undirected graph using adjacency list representation
class Graph:
def __init__(self, vertices):
self.V = vertices # No. of vertices
self.graph = defaultdict(list) # default dictionary to store graph
self.Time = 0
# function to add an edge to graph
def addEdge(self, u, v):
self.graph[u].append(v)
self.graph[v].append(u)
# This function removes edge u-v from graph
def rmvEdge(self, u, v):
for index, key in enumerate(self.graph[u]):
if key == v:
self.graph[u].pop(index)
for index, key in enumerate(self.graph[v]):
if key == u:
self.graph[v].pop(index)
# A DFS based function to count reachable vertices from v
def DFSCount(self, v, visited):
count = 1
visited[v] = True
for i in self.graph[v]:
if visited[i] == False:
count = count + self.DFSCount(i, visited)
return count
# The function to check if edge u-v can be considered as next edge in
# Euler Tour
def isValidNextEdge(self, u, v):
# The edge u-v is valid in one of the following two cases:
# 1) If v is the only adjacent vertex of u
if len(self.graph[u]) == 1:
return True
else:
'''
2) If there are multiple adjacents, then u-v is not a bridge
Do following steps to check if u-v is a bridge
2.a) count of vertices reachable from u'''
visited = [False] * (self.V)
count1 = self.DFSCount(u, visited)
'''2.b) Remove edge (u, v) and after removing the edge, count
vertices reachable from u'''
self.rmvEdge(u, v)
visited = [False] * (self.V)
count2 = self.DFSCount(u, visited)
# 2.c) Add the edge back to the graph
self.addEdge(u, v)
# 2.d) If count1 is greater, then edge (u, v) is a bridge
return False if count1 > count2 else True
# Print Euler tour starting from vertex u
def printEulerUtil(self, u):
# Recur for all the vertices adjacent to this vertex
for v in self.graph[u]:
# If edge u-v is not removed and it's a a valid next edge
if self.isValidNextEdge(u, v):
print("%d-%d " % (u, v)),
self.rmvEdge(u, v)
self.printEulerUtil(v)
'''The main function that print Eulerian Trail. It first finds an odd
degree vertex (if there is any) and then calls printEulerUtil()
to print the path '''
def printEulerTour(self):
# Find a vertex with odd degree
u = 0
for i in range(self.V):
if len(self.graph[i]) % 2 != 0:
u = i
break
# Print tour starting from odd vertex
print("\n")
self.printEulerUtil(u)
# Create a graph given in the above diagram
g1 = Graph(4)
g1.addEdge(0, 1)
g1.addEdge(0, 2)
g1.addEdge(1, 2)
g1.addEdge(2, 3)
g1.printEulerTour()
g2 = Graph(3)
g2.addEdge(0, 1)
g2.addEdge(1, 2)
g2.addEdge(2, 0)
g2.printEulerTour()
g3 = Graph(5)
g3.addEdge(1, 0)
g3.addEdge(0, 2)
g3.addEdge(2, 1)
g3.addEdge(0, 3)
g3.addEdge(3, 4)
g3.addEdge(3, 2)
g3.addEdge(3, 1)
g3.addEdge(2, 4)
g3.printEulerTour()
# This code is contributed by Neelam Yadav
print('\nExercício 20: ')
g4 = Graph(4)
g4.addEdge(0, 1)
g4.addEdge(0, 2)
g4.addEdge(2, 0)
g4.addEdge(2, 1)
g4.addEdge(1, 2)
g4.addEdge(1, 3)
g4.addEdge(2, 3)
g4.addEdge(3, 1)
g4.printEulerTour()