Cod sursa(job #2797688)

Utilizator Andrei_SturzuAndrei Sturzu Andrei_Sturzu Data 10 noiembrie 2021 14:03:56
Problema Componente tare conexe Scor 30
Compilator py Status done
Runda Arhiva educationala Marime 6.23 kb
from collections import defaultdict
from collections import deque


class Graph:
    def __init__(self, nodes):
        self.nodes = nodes
        self.neighbours = defaultdict(list)


    def addDirectedEdge(self, u, v):
        self.neighbours[u].append(v)


    def addUndirectedEdge(self, u, v):
        self.neighbours[u].append(v)
        self.neighbours[v].append(u)


    def addTransposeEdge(self, u, v):
        self.neighbours[v].append(u)


    def deleteNodes(self, *nodes):
        for node in nodes:
            del self.neighbours[node]
            self.nodes -= 1
        return self


    def transpose(self):
        if self.nodes > 0:
            transposed_graph = defaultdict(list)
            for source, targets in self.neighbours.items():
                for target in targets:
                    transposed_graph[target].append(source)

            t = Graph(self.nodes)
            t.neighbours = transposed_graph
            return t
        else:
            return None


    def bfs(self, source):
        visited = {i: False for i in range(1, self.node + 1)}

        queue = []

        queue.append(source)
        visited[source] = True

        while queue:
            source = queue.pop(0)
            print(source, sep=' ')
            for i in self.neighbours[source]:
                if not visited[i]:
                    queue.append(i)
                    visited[i] = True


    def bfs_cost(self, source):
        visited = {i: False for i in range(1, self.nodes + 1)}

        queue = []
        cost = {i: 0 for i in range(1, self.nodes + 1)}

        queue.append(source)
        visited[source] = True

        while queue:
            source = queue.pop(0)
            print(source, sep=' ')
            for i in self.neighbours[source]:
                if not visited[i]:
                    queue.append(i)
                    cost[i] = cost[source] + 1
                    visited[i] = True

        for node in self.neighbours.keys():
            if not visited[node]:
                cost[node] = -1

        return cost


    def dfs(self, source, visited):
        visited[source] = True

        for i in self.neighbours[source]:
            if not visited[i]:
                self.dfs(i, visited)

        return visited


    def numberOfConnectedComponents(self):
        visited = {i: False for i in range(1, self.nodes + 1)}
        count = 0

        for node in range(1, self.nodes + 1):
            if not visited[node]:
                self.dfs(node, visited)
                count += 1

        return count

    def dfs_Kosaraju1(self, source, visited, stack):
        visited[source] = True

        for node in self.neighbours[source]:
            if not visited[node]:
                self.dfs_Kosaraju1(node, visited, stack)
        stack.append(source)


    def dfs_Kosaraju2(self, source, visited, components, count):
        visited[source] = True
        components[count].append(source)

        transpose_g = self.transpose()

        for node in transpose_g.neighbours[source]:
            if not visited[node]:
                self.dfs_Kosaraju2(node, visited, components, count)


    def SCC_Kosaraju(self):
        stack = deque()
        components = defaultdict(list)
        count = 0

        visited = {i: False for i in range(1, self.nodes + 1)}

        for node in list(self.neighbours.keys()):
            if not visited[node]:
                self.dfs_Kosaraju1(node, visited, stack)

        visited = {i: False for i in range(1, self.nodes + 1)}

        while stack:
            node = stack.pop()
            if not visited[node]:
                count += 1
                self.dfs_Kosaraju2(node, visited, components, count)

        return components


    def topoSortDFS(self, soruce, visited, stack):
        visited[soruce] = True

        for neighbour in self.neighbours[soruce]:
            if not visited[neighbour]:
                self.topoSortDFS(neighbour, visited, stack)

        stack.append(soruce)


    def topologicalSort(self):
        stack = deque()
        result = []

        visited = {i: False for i in range(1, self.nodes + 1)}

        for node in list(self.neighbours.keys()):
            if not visited[node]:
                self.topoSortDFS(node, visited, stack)

        while stack:
            node = stack.pop()
            result.append(node)

        return result


# STRONGLY CONNECTED COMPONENTS
file_ctc = 'ctc.in'

with open(file_ctc, 'rt') as f:
    content = f.readlines()
    content = [line.strip().split() for line in content]
    content = [[int(x) for x in line] for line in content]
    N, M = content[0][0], content[0][1]


g = Graph(N)
for edges in content[1:]:
    g.addDirectedEdge(edges[0], edges[1])

visited = {i: False for i in range(1, g.nodes + 1)}
result = g.SCC_Kosaraju()

with open('ctc.out', 'wt') as f:
    f.write(str(len(result.keys())))
    f.write('\n')
    for component in result.values():
        for node in component:
            f.write(str(node))
            f.write(' ')
        f.write('\n')

## TOPOLOGICAL SORT
# file_sortaret = 'sortaret.in'
#
# with open(file_sortaret, 'rt') as f:
#     content = f.readlines()
#     content = [line.strip().split() for line in content]
#     content = [[int(x) for x in line] for line in content]
#     N, M = content[0][0], content[0][1]
#
#
# g = Graph(N)
# for edges in content[1:]:
#     g.addDirectedEdge(edges[0], edges[1])
#
# visited = {i: False for i in range(1, N + 1)}
#
# result = g.topologicalSort()
#
# with open('sortaret.out', 'wt') as f:
#     for node in result:
#         f.write(str(node))
#         f.write(' ')

## NUMBER OF CONNECTED COMPONENTS
# file_dfs = 'dfs.in'
#
# with open(file_dfs, 'rt') as f:
#     content = f.readlines()
#     content = [line.strip().split() for line in content]
#     content = [[int(x) for x in line] for line in content]
#     N, M = content[0][0], content[0][1]
#
# g = Graph(N)
# for edges in content[1:]:
#     g.addUndirectedEdge(edges[0], edges[1])
#
# result = g.numberOfConnectedComponents()
#
# with open('dfs.out', 'wt') as f:
#     f.write(str(result))