Algorithm - singlePointOfFailure(connections)

1 분 소요

Problem

  • connections 는 2 dimensional array로, connections[i][j]가 1이면, node i j 가 연결되어 있음을 의미한다(o/w 0)
  • connections를 이용하여 네트워크를 그릴 수 있으며, 입력받은 connections의 경우 모든 노드가 연결되어 있다.
  • 이 때 특정한 edge를 하나 자르면, 해당 네트워크에서 모든 노드 간에 연결되는 것이 아니고, 어떤 노드들의 경우 연결성이 끊어진다.
  • 그림으로 설명하면 좋은데, 예를 들어, 0-1-2-3-4 의 네트워크라면, 이 사이의 어떤 edge를 끊어도 네트워크 전체의 연결성은 끊어지게 된다.
    • 해당 edge가 전체 네트워크의 유동성에 가장 중요한 역할을 가진 edge라고 표현할 수도 있다.

solution

  • node i, j 에 대해서, 서로 직접 연결되어 있으며 또 다른 path가 없는 경우를 모두 카운트해주면 된다.
  • 처음에는 다른 방식으로 풀었으나(왠지 graph 문제니까, bright한 방법이 있지 않을까? 하고 고민하다가 실패함) 결국 tree search(BFS) 형태로 돌아옴.
  • graph를 모델링하는 다양한 방법이 있을 수 있다. linked list도 가능하지만, 여기서는 간단하게 딕셔너리로 구현하였다.
  • IsConnectedTwice(i, j)는 내부 함수로, 두 node 간에 연결되어 있는 방법이 두 번인지를 True/False로 리턴해준다.
def singlePointOfFailure(connections):
    con_d = {}
    for i, row in enumerate(connections):
        con_d[i]=[]
        for j, elem in enumerate(row):
            if elem==1:
                con_d[i].append(j)
    def IsConnectedTwice(i, j):
        if j in con_d[i]:
            # count 1
            visited = set([j])
            cur_nodes = set(con_d[j]).difference(visited)
            cur_nodes = set(con_d[j]).difference([i])
            while True:
                l = len(visited)
                for c in cur_nodes:
                    visited.add(c)
                if i in visited:
                    return True
                if l==len(visited):
                    return False
                temp_nodes = set()
                for k in cur_nodes:
                    temp_nodes.update(con_d[k])
                cur_nodes = temp_nodes.difference(visited)
        else:
            return False
    r = 0 
    for i in range(0, len(connections)):
        for j in range(i+1, len(connections)):
            #print("{}, {} : {}".format(i, j, IsConnectedTwice(i, j)))
            if IsConnectedTwice(i, j)==False and connections[i][j]==1:
                r+=1
    return r

drawing graph

  • connections을 매트릭스로만 보는 것보다, 그림으로 직접 그려봐야, 지금 내가 잘하고 있는지를 확인할 수 있는데, 간단하게 그림을 그릴 수 있는 코드를 첨부하였다.
import networkx as nx
import matplotlib.pyplot as plt 

def draw_connections(connections):
    g = nx.Graph()
    for i in range(0, len(connections)):
        for j in range(0, len(connections)):
            if connections[i][j]==1:
                g.add_edge(i, j)
    nx.draw_networkx(g)
    plt.show()
draw_connections(connections)

댓글남기기