【问题标题】:Algorithm for removing edges in a connected graph去除连通图中边的算法
【发布时间】:2014-09-11 18:01:00
【问题描述】:

问题: 你有一个连接的,而不是有向图。有N个顶点。你还有一个结构数组:

struct Edge
{
     int a;
     int b;
}

数组 StructArray 表示所有边。数组的大小为 M。求最小值 k,以便在从 StructArray 中移除除那些边:[0...k-1] 之外的所有边后,图仍然是连通的。

我的想法 我不知道如何处理这个结构,所以我正在重建它(这可能是一个非常糟糕的方法),以创建一个邻接列表:

vector < vector <int> > edges_list(N);

现在从 StructArray 的末尾开始,每次你想删除一条边时,你都在检查边列表:

edges_list[a].size() > 1 && edges_list[b].size() > 1;

您如何看待这个解决方案?好/坏?你还有别的吗?也许保留结构而不创建新结构?

【问题讨论】:

  • 你的方法对我来说看起来不错。如果边的数量很大,您可能通过将其中一个向量转换为地图来提高效率;但你可能不会这样做,除非后来证明这样做很重要。否则,您的方法看起来不错。

标签: c++ algorithm


【解决方案1】:

我会以增量而不是递减的方式解决这个问题:从一个空图开始,一条接一条地添加边,直到图连接起来。使用Kruskal's algorithm 中的不相交集数据结构来检测何时只有一个连接的组件。

【讨论】:

  • 但是例如,如果有 1.000.000 条边并且所有这些边都需要以便可以连接图,那么程序应该在测试第一条边后立即结束 (StructArray[m-1] )。
  • @Randolph 是的,但是这种方法的渐近运行时间无论如何都非常接近线性。
【解决方案2】:

这是图论中一个众所周知的问题的变体,称为Minimum Spanning Tree 问题的发现。不同之处在于,在您的问题中,边缘没有加权。换句话说,你所有的边都具有相同的权重,这意味着你的问题在某种程度上比原来的问题更容易。

解决这个问题最常用的两种算法是Prim's algorithmKruskal's algorithm(David Eisenstat 提到过)。阅读问题和其中一种算法(我个人认为 Prim 的算法更直观),并尝试实现它(或者在网上找到现有的实现,我相信有很多!)。

【讨论】:

    【解决方案3】:

    我认为创建邻接列表是个好主意。

    但是,我认为算法不正确。假设你有 A 连接到 B,B 连接到 C,C 连接到 D。我认为你的算法会错误地认为它可以删除边 B 到 C,但这实际上断开了图形。

    这是一个称为寻找生成树的标准问题。

    修复它的一种方法是从任何节点开始,然后简单地进行深度优先搜索,直到到达所有节点。

    【讨论】:

    • 你是对的......你知道如何解决它吗?
    【解决方案4】:

    嗯,最小边数总是N-1,(也就是一棵树的边数)

    所以如果你只想找到k,答案是N - 1。

    要找到一组有效的边,只需使用简单的BFSDFS,因为这些搜索总是形成一棵连通树(它们从不访问顶点两次!)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-14
      • 1970-01-01
      • 2013-01-09
      • 1970-01-01
      相关资源
      最近更新 更多