在多项式时间内使用DFS的最小命中集算法

时间:2016-02-15 05:01:31

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

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

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

有人能帮我算一下我写的算法的运行时间吗?它功能齐全,但似乎非常低效。感谢

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

我使用了这篇文章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;
    }
}

2 个答案:

答案 0 :(得分: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-Complete问题,通过集合封面 - https://en.wikipedia.org/wiki/Set_cover_problem#Hitting_set_formulation

答案 1 :(得分:0)

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

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