【问题标题】:Checking if removing an edge in a graph will result in the graph splitting检查删除图中的边是否会导致图分裂
【发布时间】:2011-06-16 14:38:16
【问题描述】:

我有一个图形结构,我在其中一个接一个地删除边,直到满足某些条件。我的大脑已经完全停止运转,我找不到有效的方法来检测删除一条边是否会导致我的图分裂为两个或更多图。

蛮力解决方案是执行 bfs,直到可以从一个随机节点到达所有节点,但是对于大型图,这将花费太多时间...

有什么想法吗?

编辑:经过一番搜索,似乎我正在尝试做的与 fleury 算法非常相似,我需要在其中查找边缘是否是“桥”。

【问题讨论】:

  • 你为什么要一一去除边缘?许多算法一个一个地删除边缘来完成其他事情。也许有更简单的方法来做你想做的事?

标签: path directed-graph


【解决方案1】:

在移除时使图形断开连接的边称为“bridges”。您可以在 O(|V|+|E|) 中找到它们,只需对整个图进行一次深度优先搜索。一个相关的算法会找到所有的“连接点”(如果删除,会使图形断开连接的节点)。两个关节点之间的任何边缘都是一个桥(您可以在所有边缘的第二次测试中对其进行测试)。

//
// g: graph; v: current vertex id; 
// r_p: parents (r/w); r_a: ascents (r/w); r_ap: art. points, bool array (r/w)
// n_v: bfs order-of-visit 
//
void dfs_art_i(graph *g, int v, int *r_p, int *r_v, int *r_a, int *r_ap, int *n_v) {
    int i;
    r_v[v] = *n_v;
    r_a[v] = *n_v;
    (*n_v) ++;

    // printf("entering %d (nv = %d)\n", v, *n_v);
    for (i=0; i<g->vertices[v].n_edges; i++) {
        int w = g->vertices[v].edges[i].target;
        // printf("\t evaluating %d->%d: ", v, w);
        if (r_v[w] == -1) {    
            // printf("...\n");
            // This is the first time we find this vertex
            r_p[w] = v;
            dfs_art_i(g, w, r_p, r_v, r_a, r_ap, n_v);
            // printf("\n\t ... back in %d->%d", v, w);
            if (r_a[w] >= r_v[v]) {
                // printf(" - a[%d] %d >= v[%d] %d", w, r_a[w], v, r_v[v]);
                // Articulation point found
                r_ap[i] = 1;
            }
            if (r_a[w] < r_a[v]) {
                // printf(" - a[%d] %d < a[%d] %d", w, r_a[w], v, r_a[v]);
                r_a[v] = r_a[w];
            }
            // printf("\n");
        }
        else {
            // printf("back");
            // We have already found this vertex before
            if (r_v[w] < r_a[v]) {
                // printf(" - updating ascent to %d", r_v[w]);
                r_a[v] = r_v[w];
            }
            // printf("\n");
        }
    }
}

int dfs_art(graph *g, int root, int *r_p, int *r_v, int *r_a, int *r_ap) {
    int i, n_visited = 0, n_root_children = 0;
    for (i=0; i<g->n_vertices; i++) {
        r_p[i] = r_v[i] = r_a[i] = -1;
        r_ap[i] = 0;
    }
    dfs_art_i(g, root, r_p, r_v, r_a, r_ap, &n_visitados);    

    // the root can only be an AP if it has more than 1 child
    for (i=0; i<g->n_vertices; i++) {
        if (r_p[i] == root) {
            n_root_children ++;
        }
    }
    r_ap[root] = n_root_children > 1 ? 1 : 0;
    return 1;
}

【讨论】:

    【解决方案2】:

    如果你删除顶点 A 和 B 之间的链接,你不能只检查在删除边之后你仍然可以从 B 到达 A 吗?这比从 random 节点获取 所有 节点要好一些。

    【讨论】:

      【解决方案3】:

      如何选择要删除的边缘? 您能详细介绍一下您的问题领域吗?

      您的图表有多大?也许 BFS 就好了!

      在你写下你试图找出一条边是否是一座桥之后,我建议 您按照 betweenness 度量的降序删除边缘。

      本质上,介数是衡量图中边(或顶点)中心性的指标。 具有较高介数值的边更有可能成为图中的桥梁。

      在网上查了一下,算法叫'Girvan-Newman algorithm'。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-10
        • 2019-01-16
        • 1970-01-01
        • 2014-10-11
        • 2010-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多