【问题标题】:Minimum Hitting Set algorithm using DFS in polynomial time在多项式时间内使用 DFS 的最小命中集算法
【发布时间】:2016-02-15 05:01:30
【问题描述】:

我需要编写一个算法来找到给定无向图的最小命中集 F,即在图的每个循环中包含最小边的集合,使得 F 和任何给定循环的交集不为空。我编写了一个算法,它使用深度优先搜索来查找图中所有可能的循环,然后在每个循环中获取最小边并将其放入一个集合中(我在其中删除重复项)。

但是,我被要求在多项式时间内完成这项任务,我不太确定我的算法能做到这一点。例如,我添加了一个计数器来解决从 A 开始的以下图表,并且我的 DFS 方法被调用了 34 次:

谁能帮我算出我写的算法的运行时间?它很实用,但似乎效率很低。谢谢

这是我的 DFS 方法的代码。 MHS 是类似节点的基本数据结构。它们有一个标签和一个链接列表,其中包含一个端点(另一个节点)和一个与之关联的整数值)。循环只是一个包含所有循环的 ArrayList,它们本身表示为边缘值的 ArrayList。

我使用了这篇文章https://stackoverflow.com/a/549312/1354784中描述的方法。

public static void DFS(MHS v){
    ++counter;
    if(v.visited){
        MHS current=v.predecessor;
        ArrayList<Integer> currEdges=new ArrayList<Integer>();
        currEdges.add(getEdgeValue(current, v));
        while(!current.equals(v)){
            MHS p=current.predecessor;
            if(p==null)
                break;
            currEdges.add(getEdgeValue(p, current));
            current=p;
        }
        if(currEdges.size()>0)
            cycles.add(currEdges);
    }else{
        v.visited=true;
        for(int i=0;i<v.links.size();i++){
            MHS w=v.links.get(i).next;
            if(v.predecessor==null || !v.predecessor.equals(w)){
                if(v.visited){
                    MHS ok=w.predecessor;
                    w.predecessor=v;
                    DFS(w);
                    w.predecessor=ok;
                }else{
                    w.predecessor=v;
                    DFS(w);
                }
            }
        }
        v.visited=false;
    }
}

【问题讨论】:

    标签: java algorithm recursion graph depth-first-search


    【解决方案1】:

    你真的从找出图中的每个循环开始吗?如果你有完整的图 Kn,其中每对节点都是连接的,那么任何大小的节点的每个有序集合都定义了一个循环,因此循环的数量是指数级的。

    你可以试试

    While (there are any cycles left)
      Find a cycle
      find the shortest edge in that cycle
      remove that edge from the graph
    

    这应该是多项式时间,因为每次循环 while 循环都会从图中删除一条边,迟早你会用完边。

    但我不确定这是否能回答您的问题。我还注意到,命中集合的标准定义是一个 NP 完全问题,通过集合覆盖 - https://en.wikipedia.org/wiki/Set_cover_problem#Hitting_set_formulation

    【讨论】:

    • 我想我明白了。为了得到命中集,我只需要考虑每个循环中的最小边,所以我认为我可以找到图中的最小生成树,而不是在图中找到所有循环,并且这些边对应于我的边寻找。
    【解决方案2】:

    事实证明,没有必要考虑图表中的所有周期。我们可以简单地调整最小生成树的循环属性,即循环中成本最高的边不会包含在 MST 中。同样的属性,应用于最大生成树,告诉我们循环中成本最低的边不会包含在最大 ST 中。

    为了解决这个问题,我们只需要找到 G 的最大 ST(通过适应 Kruskal 算法)并返回 G 中所有尚未添加到树中的边。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-05
      • 1970-01-01
      • 1970-01-01
      • 2012-01-03
      • 1970-01-01
      • 2013-04-17
      • 2014-12-15
      • 2021-02-24
      相关资源
      最近更新 更多