88 lines
2.2 KiB
Python
88 lines
2.2 KiB
Python
# Detecting cycles in a given adjacency list
|
|
# First we're given N for how many nodes we'll have
|
|
n = int(input())
|
|
|
|
# Next we're given the N nodes
|
|
class Node:
|
|
def __init__(self, name, in_degree=0):
|
|
self.name = name
|
|
self.in_degree = in_degree
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
def __repr__(self):
|
|
return f'{self.name} {self.in_degree}'
|
|
|
|
nodes = []
|
|
for i in range(0, n):
|
|
nodes.append(Node(input().strip()))
|
|
|
|
# Next we're given how many nodes and edges we have total ex:n e
|
|
_node_count, _edge_count = input().split()
|
|
_node_count = int(_node_count)
|
|
_edge_count = int(_edge_count)
|
|
edges = []
|
|
for i in range(0, _edge_count):
|
|
_from, _to = input().split()
|
|
edges.append([int(_from), int(_to)])
|
|
|
|
# Now we calculate the in-degrees
|
|
for edge in edges:
|
|
# take the target index in nodes and increment its in_degree
|
|
nodes[edge[1]].in_degree += 1
|
|
|
|
# Quick check if we exceed the max count of edges
|
|
max_edges = ((_node_count//2) * (_node_count -1))+1
|
|
#print(f'{_edge_count}/{max_edges}')
|
|
if _edge_count >= max_edges:
|
|
print('Cycle!')
|
|
exit(0)
|
|
|
|
# building the queue of items based on in-degrees
|
|
def add_nodes(_deg):
|
|
ret = []
|
|
for i in nodes:
|
|
if i.in_degree == _deg:
|
|
ret.append(i)
|
|
|
|
return ret
|
|
|
|
def find_neighbors(node):
|
|
ret = []
|
|
for i in edges:
|
|
if i[1] == nodes.index(node):
|
|
ret.append(nodes[i[0]])
|
|
|
|
|
|
nodes_mirror = [i for i in nodes]
|
|
|
|
# add the lowest in-degree nodes to our queue, up to the higher ones
|
|
budget_q = []
|
|
for i in range(0, max_edges):
|
|
budget_q += add_nodes(i)
|
|
|
|
visited = []
|
|
i = 0
|
|
while len(budget_q) > 0:
|
|
# add the first thing to the visited list
|
|
#visited.append(budget_q[0])
|
|
# Decrememt the neighbors' in_degree
|
|
for i in edges:
|
|
_from = i[0]
|
|
_to = i[1]
|
|
if nodes[_from] == budget_q[0]:
|
|
_neighbor = nodes_mirror[_to]
|
|
_neighbor.in_degree -= 1
|
|
if _neighbor.in_degree == 0:
|
|
visited.append(nodes_mirror[_to])
|
|
budget_q.append(_neighbor)
|
|
# remove whats at the front
|
|
del budget_q[0]
|
|
|
|
# then compare the lenthts
|
|
if len(visited) != (len(nodes) + len(edges)):
|
|
print('Cycle!')
|
|
else:
|
|
print('No cycle!')
|