C++ 无向加权图中求所有圈权的有效算法

C++ 无向加权图中求所有圈权的有效算法,c++,algorithm,graph,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; } d

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

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
}

for(inti=0;i因为不是每个人都以相同的方式定义它,所以我假设

  • Weights位于边上,而不是顶点上
  • 循环中唯一一个多次访问的顶点是开始/结束顶点
  • 单个顶点或两个连接的顶点是不循环的,即它至少需要三个顶点
  • 在图形中的两个顶点之间,不能有多条边(无“多重图”)
以下步骤可确定是否(至少)存在一个奇数加权循环:

  • 删除只有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,确定和是否奇数与确定边是否“计数”相同这很奇怪
  • 现在,要检查二分性/2颜色:
    • 您可以在此处使用修改的DFS
    • 顶点可以是未知的、0或1。开始时,将0指定给单个顶点,所有其他顶点都是未知的。0顶点的未知邻居始终为1,1顶点的未知邻居始终为0
    • 在检查某个顶点的相邻点是否已被访问时,也要检查其数量是否与您现在处理的顶点不同。如果不是,则您刚刚发现图形具有奇数weigthed循环,您可以停止所有操作
    • 如果您到达DFS的末尾而没有找到它,则不存在奇数加权循环
    • 对于实现,请注意,当仍然存在未访问的顶点时,即如果有一个断开连接的图,则可以到达DFS的“结束”。如果是这样,则需要将剩余的一个顶点设置为已知数字(0),并从此处继续DFS

复杂性
O(V+E)
(这一次,实际上,不是指数型的东西,也不是有效的解决方案)。

在特定情况下,当图形完成时,任何节点序列都构成一个循环。因此(如果我正确理解需求),在最坏的情况下,一个好的算法似乎不可能不要求指数复杂度。正如queryman所说,循环的数量可能是指数级的。你真的需要每个权重吗(那么除了指数级的多个结果之外,没有其他方法了),或者只是min、max或类似的东西?请看这里@deviantfan,准确地说,我需要知道任何重量是否是奇数。但它不需要计算所有重量吗?(重量==一个周期的重量)@yobro97不,不需要。我正在写一个答案。。。