簡體   English   中英

在無向圖中查找所有非重疊環

[英]Finding all non overlapping cycles in an undirected graph

我需要在無向圖上找到所有簡單的非重疊循環。 為了找到所有現有的循環,我制作了我在這里找到的算法的 Objective-C 版本:

在無向圖中查找所有循環

@interface HSValue : NSObject
@property (nonatomic, assign) CGPoint point;
@end
@implementation HSValue
@end


@interface CyclesFinder ()
@property (nonatomic, strong) NSMutableArray <NSArray<HSValue *>*> *cycles;
@property (nonatomic, strong) NSArray <NSArray<HSValue*>*> *edges;
@end

@implementation CyclesFinder

-(void)findCyclesInGraph:(NSArray <NSArray<HSValue*>*> *)edges {
   self.edges = edges;
   for (NSInteger i=0; i < self.edges.count; i++) {
        for (NSInteger j=0; j < self.edges[i].count; j++) {
            [self findNewCycles:@[self.edges[i][j]]];
        }
    }
}

-(void)findNewCycles:(NSArray <HSValue *> *)path {

    HSValue *startNode = path[0];
    HSValue *nextNode;
    NSArray <HSValue *> *sub;

    for (NSInteger i=0; i < self.edges.count; i++) {
        NSArray <HSValue *> *edge = self.edges[i];
        if ([edge containsObject:startNode]) {
            if ([edge[0] isEqual:startNode]) {
                nextNode = edge[1];
            }
            else {
                nextNode = edge[0];
            }
        }
        else {
            nextNode = nil;
        }

        if (![path containsObject:nextNode] && nextNode) {
            sub = @[nextNode];
            sub = [sub arrayByAddingObjectsFromArray:path];
            [self findNewCycles:sub];
        }
        else if (path.count > 2 && [nextNode isEqual:path.lastObject]) {
            if (![self cycleExist:path]) {
                [self.cycles addObject:path];
                break;
            }
        }
    }
}

-(BOOL)cycleExist:(NSArray <HSValue*> *)path {
    path = [path sortedArrayUsingSelector:@selector(compare:)];
    for (NSInteger i=0; i < self.cycles.count; i++) {
        NSArray <HSValue *> *cycle = [self.cycles[i] sortedArrayUsingSelector:@selector(compare:)];
        if ([cycle isEqualToArray:path]) {
            return TRUE;
        }
    }

    return FALSE;
}

上面的算法工作正常(即使它不是很有效)並且它從附圖上的圖表中找到所有可能的循環(請參見下圖):

ABHGFDEA(有效)

BCIHB(有效)

GHILKG(有效)

FGKJF(有效)

FGHILKJF(無效)

ABCIHGFDEA(無效)

ABCILKJFDEA(無效)

ABCIHG--KJFDEA(無效)

ABHILKGFDEA(無效)

ABHGKJFDEA(無效)

ABCILKGFDEA(無效)

BCILKGHB(無效)

BCILKJFGHB(無效)

但是,當我運行上述算法時,我只想得到我在左側示例中用彩色多邊形突出顯示的那些循環。 我不想要的是像右側示例中的循環。

在此處輸入圖片說明

我的第一個想法是重疊循環將是一個包含來自任何其他循環的所有點的循環,但這並不總是正確的。 有人可以指出我正確的方向嗎? 是否可以修改上述算法,使其僅找到不重疊的循環,否則在找到所有循環來過濾它們后我應該怎么做?

僅在無向圖中沒有足夠的信息來確定哪些循環是哪些。 例如,考慮以下 2 個圖產生相同的無向圖:

A-----B      E-------------F
|     |       \           /
C-----D        \ A-----B /
|     |         \|     |/
E-----F          C-----D

但是對於左側的圖表,您需要循環 ABDCA 和 CDFEC,而對於右側的圖表,您需要循環 ABDCA 和 EFDBACE。 因此,從圖中推斷出的無向圖是不夠的——您需要以某種方式合並來自原始圖中的空間信息。

我正在解決同樣的問題,您的很多評論都很有幫助,尤其是所有邊的每一側都有一個區域的評論。 因此,您可以說每條邊都有一個“左側區域”和一個“右側區域”。

您可以按任何順序將所有圖形邊添加到隊列中。 查看第一條邊,選擇靠近原點的頂點。 移動到最逆時針的鄰居。 繼續這個直到你到達你的起始頂點。 所有這些邊都限定了您的第一個區域。 我會給它一個唯一的 ID 並將它分配給這些邊緣的“左區域”屬性。

查看隊列中的第一個邊緣並檢查它是否有“左側區域”。 如果它確實檢查它是否有“正確區域”,如果它沒有以順時針方式進行並找到正確的區域。 如果它分配了兩個區域,則將其出列並獲取下一個區域。

應該是 O(e+v) 這么快,對吧?

這是一點點意識流,但我想把它寫下來。 我將為我的實際應用編寫算法,並在發現問題時進行調整。

當然,我願意接受反饋和建議:)

暫無
暫無

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

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