Representação ótima de grafos

59 views
Skip to first unread message

Josue Andrade Gomes

unread,
Aug 1, 2021, 10:55:35 AM8/1/21
to ccppb...@googlegroups.com

Olá amigos C++ers, puzzle para este domingo:
Seja a seguinte implementação de um grafo.
A lista de vértices como um std::vector e a lista de adjacências como um std::vector de índices do primeiro std::vector.

    std::vector<ValueType> V;
    std::vector<std::vector<size_t>> adj;

Seja esta implementação:

    size_t find_vertex(ValueType const& v) const
    {
        auto it = std::find(V.begin(), V.end(), v);
        if (it != V.end()) {
            std::distance(V.begin(), it);
        }
        return npos;
    }

    size_t add_vertex(ValueType&& v)
    {
        V.emplace_back(v);
        adj.emplace_back(std::vector<size_t>{});
        return V.size() - 1;
    }

    void add_edge(ValueType&& v, ValueType&& w)
    {
        auto iv = find_vertex(v);
        if (iv == npos) {
            iv = add_vertex(std::move(v));
        }
        auto iw = find_vertex(w);
        if (iw == npos) {
            iw = add_vertex(std::move(w));
        }
        adj[iv].push_back(iw);
    }

Código em https://godbolt.org/z/9MYE68fqW

A complexidade de add_edge é O(n) por causa da chamada à std::find em find_vertex. A complexidade de add_vertex é O(1).
No meu caso o número de vértices não é trivial podendo chegar a milhões.
Uma maneira e mitigar isso é mudar a implementação de V para um std::set (ou std::multiset) de uma struct que une o valor e a lista de adjacências:

template<class ValueType>
class Graph {
public:
    struct VertexType {
       ValueType value;
       std::vector<typename std::set<VertexType>::const_iterator> adj;
    };
    std::set<VertexType> V;

    ....
};

As implementações de find_vertex, add_vertex e add_edge seriam todas O(log n).

Quais são as suas opiniões? Sugerem outro caminho?

Abraços,
Josué

Reply all
Reply to author
Forward
0 new messages