Recursos-LCC

Um arquivo de todo material que consegui reunir, pertinente ao curso de LCC da UM.

View on GitHub

LA2 | Torneio 2 (2021/2022) | Centros


'''
Neste problema pertende-se calcular quais os vértices centrais
de um grafo pesado não orientado.
A excentricidade de um vértice é a distância desse vértice
ao vértice mais afastado. Os vértices centrais (ou centros) de
um grafo são os que tem excentricidade mínima.
Os vértices do grado são identificados por letras do alfabeto.
O grafo será descrito através de uma sequência de arestas. Cada
aresta é descrita por uma string onde o primeiro e último caracteres
identificam os vértices adjacentes e os digitos no meio o peso da 
respectiva aresta.
A função deverá devolver a lista com todos os centros ordenados
alfabeticamente.
Se o grafo não for ligado deve devolver None.
'''

def build(arestas):   
    adj = {}
    for aresta in arestas:
        if len(aresta) == 0:
            continue
        if len(aresta) <= 2:
            adj[aresta[0]] = {}
        else:
            if aresta[0] not in adj:
                adj[aresta[0]] = {}
            if aresta[-1] not in adj:
                adj[aresta[-1]] = {}
            if aresta[-1] in adj[aresta[0]]:
                if adj[aresta[0]][aresta[-1]] < int(aresta[1:-1]):
                    continue
            adj[aresta[0]][aresta[-1]] = int(aresta[1:-1])
            adj[aresta[-1]][aresta[0]] = int(aresta[1:-1])
    
    return adj


def bfs(adj,o):
    vis = {o}
    queue = [o]
    while queue:
         v = queue.pop(0)
         for d in adj[v]:
             if d not in vis:
                 vis.add(d)
                 queue.append(d)
    return vis


def ligado(adj): 
    for v in adj.keys():
        pai = bfs(adj, v)
        if len(pai) == len(adj.keys()):
            continue
        else:
            return False
        
    
    return True


def fw(adj):
    dist = {}
    for o in adj:
        dist[o] = {}
        for d in adj:
            if o == d:
                dist[o][d] = 0
            elif d in adj[o]:
                dist[o][d] = adj[o][d]
            else:
                dist[o][d] = float("inf")
    for k in adj:
        for o in adj:
            for d in adj:
                if dist[o][k] + dist[k][d] < dist[o][d]:
                    dist[o][d] = dist[o][k] + dist[k][d]
    return dist


def centros(arestas):
    if len(arestas) == 0:
        return []

    adj = build(arestas)

    if not ligado(adj):
        return None

    dist = fw(adj)
    minCentro = {}

    for centro, dists in dist.items():
        maxCentro = -1
        for centro2, distancia in dists.items():
            if centro == centro2:
                continue
            maxCentro = max(maxCentro, distancia)
        minCentro[centro] = maxCentro

    final = [ x for x in sorted(minCentro.items(), key = lambda x: x[1])]
    mindist = final[0][1]
    final2 = [x[0] for x in final if x[1] == mindist]

    final2.sort()
    return final2

retroceder