簡體   English   中英

從邊列表計算創建的圖形數量和每個圖形中的頂點數量

[英]Calculating the number of graphs created and the number of vertices in each graph from a list of edges

給出邊緣列表,例如,edge = [[1,2],[2,3],[3,1],[4,5]]

我需要找到創建了多少個圖,我的意思是這些邊創建了多少組元素。 然后獲取組件組中的頂點數。

但是,我需要能夠處理10 ^ 5個邊緣,而且我目前無法完成大量邊緣的任務。

我的算法當前正在獲取edge = [[1,2],[2,3],[3,1],[4,5]]的列表,如果它們有一個交集,則將每個列表合並為set,這將輸出一個新的列表,現在包含組組件,如:graphs = [[1,2,3],[4,5]]

有兩個連接的組件:[1,2,3]連接,[4,5]也連接。

我想知道是否有更好的方法來完成這項任務。

def mergeList(edges):
    sets = [set(x) for x in edges if x]
    m = 1
    while m:
        m = 0
        res = []
        while sets:
            common, r = sets[0], sets[1:]
            sets = []
            for x in r:
                if x.isdisjoint(common):
                    sets.append(x)
                else:
                    m = 1
                    common |= x
            res.append(common)
        sets = res
    return sets

我想嘗試在字典或高效的東西中這樣做,因為這太慢了。

Python中基本的迭代圖遍歷並不算太糟糕。

import collections


def connected_components(edges):
    # build the graph
    neighbors = collections.defaultdict(set)
    for u, v in edges:
        neighbors[u].add(v)
        neighbors[v].add(u)
    # traverse the graph
    sizes = []
    visited = set()
    for u in neighbors.keys():
        if u in visited:
            continue
        # visit the component that includes u
        size = 0
        agenda = {u}
        while agenda:
            v = agenda.pop()
            visited.add(v)
            size += 1
            agenda.update(neighbors[v] - visited)
        sizes.append(size)
    return sizes

你需要編寫自己的算法嗎? networkx已經有了算法。

要獲得每個組件的長度,請嘗試

import networkx as nx

G = nx.Graph()
G.add_edges_from([[1,2],[2,3],[3,1],[4,5]])

components = []
for graph in nx.connected_components(G):
  components.append([graph, len(graph)])

components
# [[set([1, 2, 3]), 3], [set([4, 5]), 2]]

您可以使用Disjoint-set數據結構:

edges = [[1,2],[2,3],[3,1],[4,5]]
parents = {}
size = {}

def get_ancestor(parents, item):
    # Returns ancestor for a given item and compresses path
    # Recursion would be easier but might blow stack
    stack = []
    while True:
        parent = parents.setdefault(item, item)
        if parent == item:
            break
        stack.append(item)
        item = parent

    for item in stack:
        parents[item] = parent

    return parent


for x, y in edges:
    x = get_ancestor(parents, x)
    y = get_ancestor(parents, y)
    size_x = size.setdefault(x, 1)
    size_y = size.setdefault(y, 1)
    if size_x < size_y:
        parents[x] = y
        size[y] += size_x
    else:
        parents[y] = x
        size[x] += size_y

print(sum(1 for k, v in parents.items() if k == v)) # 2

在上面, parents是一個字典,其中頂點是鍵,祖先是值。 如果給定的頂點沒有父級,則該值是頂點本身。 對於列表中的每個邊,兩個頂點的祖先設置相同。 請注意,當查詢當前祖先時,路徑會被壓縮,因此可以在O(1)時間內完成查詢。 這允許整個算法具有O(n)時間復雜度。

更新

如果需要組件而不僅僅是它們的數量,則可以迭代生成的dict以生成它:

from collections import defaultdict

components = defaultdict(list)
for k, v in parents.items():
    components[v].append(k)

print(components)

輸出:

defaultdict(<type 'list'>, {3: [1, 2, 3], 5: [4, 5]})

暫無
暫無

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

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