簡體   English   中英

從無向圖上刪除邊

[英]Deleting edges from an undirected graph

我有一個實現的無向圖

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
}

我該如何實施。

像這樣混合S樣式的C樣式數組和容器

vector<int> G[V];

被認為不是好風格。 為什么不使用vector< vector< int > >

關於您的具有為O (1)的erase()函數的請求,我認為您面臨一個權衡:要么您具有非常快的訪問權限,但是頻繁修改容器非常昂貴( 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.
}

自從我問這個問題以來已經很久了,但是看到它仍然沒有答案,我來補充我當時使用的解決方案。

因此,假設邊存儲在鄰接表數組中

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 ++技能來解決所有不良實踐問題,但是解決方案的要點很簡單:只保留對同級的引用。 案件結案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM