从无向图中删除边

时间:2015-04-10 16:52:17

标签: c++ graph implementation

我有一个无向图实现为

vector<int> G[V];

list<int> G[V];

,让我没有区别,我需要在O(1)中删除它的边。连接矩阵是不可能的,大量的椎体是10 ^ 5。问题如下:

for(int i = 0; i < G[w].size(); i++)
{
    int u = G[w][i];
    // erase G[w][i];
    // erase the edge (u, w) in G[u] in constant time
}

我该如何实现它。

2 个答案:

答案 0 :(得分:1)

自从我问这个问题以来已经很长时间了,但是看到它仍然没有答案,我来补充我当时使用的解决方案。

因此,假设边存储在邻接表数组中

std::list<Edge> G[V];

我们可以将Edges定义如下:

struct Edge {
    int vertex;
    std::list<Edge>::iterator siblingIterator;
}

然后删除例程很简单

for(auto &edge : G[w]) {
    G[edge.vertex].erase(edge.siblingIterator);
}

G[w].clear();

由于使用列表迭代器进行删除需要花费恒定的时间,因此擦除一个无向边(因此,有向边及其反向的同级边)将花费O(1)。

从那时起,我将不再沉迷于过去,并以有限的C ++技能来修复所有不良实践,但是解决方案的要点很简单:只保留对同级的引用。结案了。

答案 1 :(得分:0)

像这样混合C风格的数组和STL的容器

vector<int> G[V];

不被认为是好风格。为什么不使用vector< vector< int > >

关于你有erase() - 函数 O (1)的请求,我认为你面临着一个权衡:要么你的访问速度非常快,要么频繁容器的修改相当昂贵(std::vector),反之亦然(std::mapstd::list,......)。

以下示例提供了请求的常量erase() - 功能,但查找要删除的元素是对数的。但也许它可以帮助你找到你想要的东西:

#include <vector>
#include <set>

typedef int Vertex;
typedef std::vector< Vertex > Vertices;

struct Edge
{
    int a;
    int b;

    Edge( int a, int b ) : a( a ), b( b ) {}

    // Needed for std::set.
    bool operator< ( const Edge & other ) const
    {
        if ( a < other.a ) return true;
        if ( a > other.a ) return false;

        return b < other.b;
    }
};

 typedef std::set< Edge > Edges;

struct Graph
{
    Vertices vertices;
    Edges edges;
};

int main( int argc, char ** argv )
{
    Graph graph;

    // Add vertices.
    graph.vertices.push_back( Vertex( 0 ) ); // Vertex 0
    graph.vertices.push_back( Vertex( 1 ) ); // Vertex 1
    graph.vertices.push_back( Vertex( 2 ) ); // Vertex 2
    graph.vertices.push_back( Vertex( 3 ) ); // Vertex 3

    // Connect vertices.
    graph.edges.insert( Edge( 0, 1 ) ); // Connect vertex 0 and vertex 1.
    graph.edges.insert( Edge( 0, 1 ) ); // Connect vertex 1 and vertex 2.
    graph.edges.insert( Edge( 1, 2 ) ); // Connect vertex 2 and vertex 3.
    graph.edges.insert( Edge( 2, 0 ) ); // Connect vertex 3 and vertex 0.

    // Remove the edge between vertices 1 and 2 again.
    Edges::iterator it = graph.edges.find( Edge( 1, 2 ) );

    if ( it != graph.edges.end() )
        graph.edges.erase( it ); // The complexity of erase() is constant, but find() logarithmic.
}