我需要编写一个算法,找到给定无向图的最小命中集F,即包含图的每个周期中最小边的集合,使得F与任何给定周期的交点不为空。我编写了一个使用深度优先搜索的算法来查找图中所有可能的周期,然后在每个周期中取最小边并将其放入一个集合中(我删除重复项)。
然而,我被要求在多项式时间内完成这项任务,我不太确定我的算法是做什么的。例如,我添加了一个计数器来解决从A开始的以下图形,我的DFS方法被调用34次:
有人能帮我算一下我写的算法的运行时间吗?它功能齐全,但似乎非常低效。感谢
这是我的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;
}
}
答案 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的所有边缘。