在无向加权图中找到所有周期权重的有效算法

时间:2017-09-02 09:44:41

标签: c++ algorithm graph

我的目标是在加权无向图中找到所有周期及其各自的权重。循环的权重定义为构成循环的路径的权重之和。我的预设算法执行以下操作:

dfs(int start, int now,int val)
{
     if(visited[now])
        return;
     if(now==start)
     {
        v.push_back(val);// v is the vector of all weights
        return;
     }
     dfs through all nodes neighbouring to now;
 }

我从每个起点呼叫dfs()

for(int i=0;i<V;++i)
{
    initialise visited[];
    for(int j=0;j<adj[i].size();++j)//  adj is the adjacency matrix
        dfs(i,adj[i][j].first,adj[i][j].second); 
//  adj is a vector of vector of pairs
// The first element of the pair is the neighbour index and the second element is the weight
}

因此,该算法的整体复杂性为O(V*E)(我认为是这样)。任何人都可以提出更好的方法吗?

1 个答案:

答案 0 :(得分:3)

由于不是每个人都以同样的方式定义它,我假设......

  • 重量位于边缘,而不是顶点
  • 多次访问的循环中唯一的顶点是起始/结束顶点
  • 单个顶点或两个连接的顶点不是循环,即。它需要至少三个顶点
  • 在图表中的两个顶点之间,不能有多个边缘(没有“多图”)

以下步骤可以确定是否(至少)存在一个奇数加权循环:

  • 删除所有只有0或1个连接边的顶点(不是必需的,但它可能更快)。
  • 通过插入新的顶点来分割每个偶数加权边(只有它们,而不是奇数加权边!)。例如。如果顶点A和B之间的egde具有权重4,则它应该变为A-Z 2和Z-B 2,或A-Z 3和Z-B 1,或类似的东西。
    • 实际重量分布并不重要,您甚至不需要保存它。因为,在此步骤之后开始,不再需要所有重量。
    • 这实际上做了什么?想想每个奇数权重是1,每一个偶数都是2.(如果存在奇数加权周期,则不会改变:如果3 + 4 + 8是奇数,那么1 + 2 + 2也是如此)。现在你将所有2分成两个1.由于现在唯一的现有权重是1,确定总和是否为奇数与确定边缘“count”是否为奇数相同。
  • 现在,检查双重性/ 2颜色:
    • 您可以在此处使用修改后的DFS
    • 顶点可以是未知的,0或1.启动时,将0分配给单个顶点,其他所有顶点都是未知的。 0顶点的未知邻居总是得到1,而1顶点的未知邻居总是得到0.
    • 在检查顶点的邻居时,如果它们已被访问过,请检查该数字是否与您正在处理的顶点不同。 如果没有,你刚发现你的图表有奇数周期,你可以停止一切。
    • 如果在没有找到DFS的情况下到达DFS结尾,则没有奇数加权循环。
    • 对于实现,请注意您仍然可以到达DFS的“结束”,同时仍有未访问的顶点,即如果您有一个断开连接的图形。如果是这样,您需要将其余顶点之一设置为已知数字(0)并从那里继续DFS。

复杂性O(V + E)(这次真的,而不是一个指数的事情或不工作的解决方案)。